ðĪŠ The Reset Strategy
The Reset Strategy is the easiest possible strategy: it sends the entire client view on every pull response, so no patch calculation is necessary at all.
Sending the entire client view on each pull this way is very inefficient, so this approach is not usually recommended. That said, we do have customers that use this strategy in production, and it works if your data changes infrequently or is very small.
Schemaâ
In addition to your own normal domain data, your backend database will need to store two additional entities to support Replicache:
// A group of related ReplicacheClients. Typically there is one per browser
// profile.
type ReplicacheClientGroup = {
// Globally unique ID, generated by Replicache.
id: string;
// Optional, but required if the application is authenticated. The userID
// that created this ReplicacheClientGroup.
userID: any;
};
// An instance of the Replicache JS class that has ever synced with the server.
type ReplicacheClient = {
// Globally unique ID, generated by Replicache.
id: string;
// The ClientGroup this client is part of.
clientGroupID: string;
// Last mutation the server has processed from this client.
lastMutationID: number;
};
Pushâ
Replicache sends a PushRequest
to the push endpoint. For each mutation described in the request body, the push endpoint should:
let errorMode = false
- Begin transaction
- Read the
ReplicacheClientGroup
forbody.clientGroupID
from the database, or default to:
{
id: body.clientGroupID,
userID
}
- Verify the requesting user owns the specified client group.
- Read the
ReplicacheClient
formutation.clientID
or default to:
{
id: mutation.clientID,
clientGroupID: body.clientGroupID,
lastMutationID: 0,
}
- Verify the requesting client group owns the requested client.
let nextMutationID = client.lastMutationID + 1
- Rollback transaction and skip this mutation if already processed (
mutation.id < nextMutationID
) - Rollback transaction and error if mutation from the future (
mutation.id > nextMutationID
) - If
errorMode != true
then:- Try to run business logic for mutation
- If error:
- Log error
set errorMode = true
- Abort transaction
- Repeat these steps at the beginning
- Write
ReplicacheClientGroup
:
{
id: body.clientGroupID,
userID,
}
- Write
ReplicacheClient
:
{
id: mutation.clientID,
clientGroupID: body.clientGroupID,
lastMutationID: nextMutationID,
}
- Commit transaction
After the loop is complete, poke clients to cause them to pull.
Pullâ
Replicache sends a PullRequest
to the pull endpoint. The endpoint should:
- Begin transaction
- Read the
ReplicacheClientGroup
forbody.clientGroupID
from the database, or default to:
{
id: body.clientGroupID,
userID
}
- Verify the requesting client group owns the requested client.
- Read all rows from the database that should be in the client view.
- Read all
ReplicacheClient
records for the requested client group. - Create a
PullResponse
with:cookie
set to the server's current timestamp as an integer.lastMutationIDChanges
set to thelastMutationID
for every client in the client group.patch
set toop:clear
followed byop:put
for every row in the view.
Exampleâ
We do not currently have an example of this strategy.
Variationsâ
Read Authorizationâ
Because of the fact that this returns a reset patch, read authorizaton works naturally. Just update the query used to build the patch in the pull response to obey whatever auth rules you like.
Early Exitâ
There is no need to process every mutation submitted to the push endpoint. You can exit early as long as lastMutationID
is set to whatever the last processed mutation was. This can ocassionally be useful if clients can accumulate large amounts of mutations while offline and you want to keep the runtime of the push handler under some limit.
Batchingâ
You don't need to process each mutation in its own transaction. The entire push can be run inside one transaction, or you can do smaller batches.