question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Sync] Update locally created records with server ids

See original GitHub issue

Using PushChanges with a locally created record uses the id generated on the client. My server ignores this id and generates it’s own id. What’s the recommended way to update the local record with the id returned from the server? If I don’t update the local id of the record, it will never receive updates from the server. Thanks

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:5
  • Comments:27 (6 by maintainers)

github_iconTop GitHub Comments

5reactions
Bessonovcommented, May 16, 2020

Yeah, still relevant.

1reaction
KennanChancommented, Jun 28, 2022

@heliojunior

I have an interface that defines an adapter to handle table changes

export interface TableChangesAdapter {
  // handles pulled changes
  toLocal(changes: SyncTableChangeSet, database: Database): Promise<SyncTableChangeSet>;
  // handles pushing changes
  toRemote(changes: SyncTableChangeSet, database: Database): Promise<SyncTableChangeSet>;
}

Then I have an implementation to handle local id

export class HandleLocalRecordsAdapter implements TableChangesAdapter {
  // if a server record has a localId, add the localId to deleted to delete local record
  toLocal(changes: SyncTableChangeSet): Promise<SyncTableChangeSet> {
    if (changes && changes.created) {
      changes.created.forEach((record: DirtyRaw) => {
        if (record.localId) {
          if (!changes.deleted) {
            changes.deleted = []
          }
          changes.deleted.push(record.localId)
        }
        return record
      })
    }
    return Promise.resolve(changes)
  }

  // if a local record is created, add a localId to keep track of the record on the next pulling
  toRemote(changes: SyncTableChangeSet): Promise<SyncTableChangeSet> {
    if (changes && changes.created) {
      changes = {
        ...changes,
        created: changes.created.map((record: DirtyRaw) => {
	       return {
	         ...record,
	         localId: record.id,
	         id: null // use null to be compatible with non-string server id
	       }
        })
      }
    }
    return Promise.resolve(changes)
  }
}

Assume we have created a local record:

const locallyCreatedRecord: User = {
	id: "random-id",
	name: "kennan"
}

Right before pushing, it will be passed into the HandleLocalRecordsAdapter.toRemote() method

const userTableChanges = {
	created: [locallyCreatedRecord],
	updated: [],
	deleted: []
}
const handledUserTableChanges = await handleLocalRecordsAdapter.toRemote(userTableChanges)

The record is transformed into this:

const modifiedLocallyCreatedRecord: User = {
	id: null,
	name: "kennan",
	localId: "random-id",
}

Then the modified changes will be pushed to the server.

The server just clones the record and generates server-side id for the cloned record.

On the next pulling, the client receives a record like this:

const remoteRecord: User = {
	id: "server-id",
	name: "kennan",
	localId: "random-id"
}

Right after pulling, it will be passed into the HandleLocalRecordsAdapter.toLocal() method

const remoteUserTableChanges = {
	created: [remoteRecord],
	updated: [],
	deleted: []
}
const handledRemoteUserTableChanges = await handleLocalRecordsAdapter.toLocal(remoteUserTableChanges)

The changes is transformed into this:

const handledRemoteUserTableChanges = {
	created: [remoteRecord],
	updated: [],
	deleted: ["random-id"]
}

The changes is then handled by watermelon db.

If you have multiple models that are related, it is the server to replace the relations with the newly generated server ids. The client data just hooks up automatically.

It’s better to start another synchronize right after the local records are pushed to the server, which is good for consistency.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Sync - WatermelonDB documentation
So a local app can create new records, generating their IDs, and the backend server will use this ID as the true ID....
Read more >
Windows Server Update Service (WSUS) to ...
Windows Server Update Service (WSUS) to Microsoft Update sync fails.
Read more >
Synchronize Offline Changes with Mobile Sync Unit | Salesforce
The syncUp methods update the server with data from the given SmartStore soup. They look for created, updated, or deleted records in the...
Read more >
How to update all properties after store.sync()? - extjs
All records returned from the store after update procedure should replace local ... out that all extjs model fields need to return in...
Read more >
How do I synchronize holdings between Alma and WorldCat?
To synchronize local holdings with OCLC by sending MARC Format for Holdings Data (MFHD) records, create a Local Holdings Record Data sync ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found