0

I'm working on a project where I have to synchronize offline data from multiple users that work on the same data in a safe way and I've started to examine how to go about this.

The first idea was of course to save time stamps and dirty flags on every row of data that needs synchronization, but this get's to risky, relying on this when more than three users work on the same data. So after researching a bit I've come across the concept of a Merkle Tree, which is used in a variety of solutions to avoid data degradation.

But I was wondering how would you go about this? I understand how to hash a value of a string, but how would you create a hash of an object? Would you take each parameter and concatenate this to each other and from this concatenation create the hash?

Consider this made up object. How would you create a sha1-hash of it and apply the Merkle Tree solution to this?

@Entity(tableName = "tasks")
data class Task(
    @PrimaryKey
    val taskId: String,

    val title: String,

    /** Status of the given task.
     * Enumerated Values: 0 (Active), 1 (Inactive), 2 (Completed)
     */
    @TypeConverters(StatusConverter::class)
    val status: Task.Status,

    @TypeConverters(DateConverter::class)
    var startDate: Date? = null,

    @Embedded
    val syncEntity: SyncEntity
)  : Syncable by syncEntity

Here's the Syncable interface:

interface Syncable {
    val createdAt: Long
    val updatedAt: Long?
    val deleted: Boolean
}

/**
 * Base class for all Room entities that are synchronized.
 */
data class SyncEntity(
    /** Specifies the point in time when an object was first created */
    @ColumnInfo(name = "created_at")
    override val createdAt: Long = System.currentTimeMillis(),

    /** Specifies the point in time when an object was last updated. If
     * the objects hasn't been updated the value returns null
     * */
    @ColumnInfo(name = "updated_at") override val updatedAt: Long? = null,

    /**
     * Specifies if an object is marked as deleted
     */
    override val deleted: Boolean = false
) : Syncable

The Task delegates to the SyncEntity to provide the implementation of the Syncable interface.

Hopefully this question makes sense?

Bohsen
  • 4,242
  • 4
  • 32
  • 58
  • 1
    `Would you take each parameter and aggregate this to each other and from this aggregation create the hash` -- basically yes depending on what you mean by "aggregate". Normally one would describe it as **concatenate**, as in convert every field to a string or byte array and append them to each other (maybe with separators). So you can hash the object's JSON representation or `.toString()` output or csv representation etc – slebetman Aug 26 '19 at 07:12
  • @slebetman Thx. *Concatenate* was the word I was looking for . And every change to a `Task` would take the hash of the previous state of `Task` and concatenate this to the new hash? And hash this to the new hash? Doh... a lot of hashing. – Bohsen Aug 26 '19 at 07:45

0 Answers0