PRODUCTS
Real-time Sync
Keep devices and users in step. Channels carry messages between everyone using your app, and the client keeps your data working while the connection comes and goes.
- Channels. Publish to a named channel and every subscriber gets the message, whichever key they use: chat, presence, live cursors, "this changed, reload it".
- Offline queueing. Writes made without a connection are queued on the device and sent when it's back. Reads of the same key keep working from the local copy.
- Optimistic updates. Show a change right away and let the client confirm it with the server, or roll it back if the server refuses it.
- Sync events. One listener tells you when something was queued, pushed, confirmed or rolled back.
Channels are polled (every 3 seconds by default), and messages are kept for 3 days: use them for live updates, and the regular read and write calls for anything you need to keep. Anyone who knows a channel's name can use it, so give it a name that's hard to guess.
| 1 | // load prefsdb.channels.v1.min.js after prefsdb.v1.min.js |
| 2 | const db = await PrefsDB.getkey("my-app", words); |
| 3 | const room = db.channel("my-app-room-42"); |
| 4 | |
| 5 | // every subscriber sees every message, oldest first |
| 6 | const stop = room.subscribe((msg) => { |
| 7 | show(msg.sender, msg.value); |
| 8 | }); |
| 9 | |
| 10 | await room.publish({ text: "hello" }); |
| 11 | |
| 12 | // later |
| 13 | stop(); |
| 1 | const db = await PrefsDB.getkey("my-app", words); |
| 2 | |
| 3 | // offline? the write is queued on the device |
| 4 | // and replayed when the connection comes back |
| 5 | await db.key("draft").write(text); |
| 6 | |
| 7 | // reads of that key are served from the local copy |
| 8 | const draft = await db.key("draft").read(); |
| 9 | |
| 10 | PrefsDB.onSyncEvent((e) => { |
| 11 | if (e.phase === "pushed") markSaved(e.key); |
| 12 | }); |
| 1 | const db = await PrefsDB.getkey("my-app", words); |
| 2 | |
| 3 | // apply locally now, confirm with the server after |
| 4 | await db.key("likes") |
| 5 | .write(likes + 1, { optimistic: true }); |
| 6 | |
| 7 | PrefsDB.onSyncEvent((e) => { |
| 8 | if (e.phase === "optimistic-rollback") { |
| 9 | // the server refused it: the old value is back |
| 10 | render(); |
| 11 | } |
| 12 | }); |
| 1 | # publish to a channel |
| 2 | curl -s -X POST "https://prefsdb.com/api/v1/channel/publish/?channel=my-app-room-42" \ |
| 3 | -H "X-Authorization: Token $KEY" -b cookies.txt \ |
| 4 | -H "Content-Type: text/plain" --data "hello" |
| 5 | |
| 6 | # fetch messages after cursor 0 |
| 7 | curl -s "https://prefsdb.com/api/v1/channel/poll/?channel=my-app-room-42&since=0" \ |
| 8 | -H "X-Authorization: Token $KEY" -b cookies.txt |
| 9 | |
| 10 | # => { "success": true, "cursor": "17", |
| 11 | # "messages": [{ "id": "17", "sender": "...", "value": "hello" }] } |