-
Notifications
You must be signed in to change notification settings - Fork 96
feat(replicache): add zeroOption
to allow Zero to hook into Replicache events
#3933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
Branch | mlaw/rep-tx-data |
Testbed | localhost |
Click to view all benchmark results
Benchmark | File Size | Benchmark Result kilobytes (KB) (Result Δ%) | Upper Boundary kilobytes (KB) (Limit %) |
---|---|---|---|
zero-package.tgz | 📈 view plot 🚷 view threshold | 1,002.65 KB(+0.07%)Baseline: 1,001.92 KB | 1,021.96 KB (98.11%) |
zero.js | 📈 view plot 🚷 view threshold | 180.87 KB(+0.02%)Baseline: 180.83 KB | 184.45 KB (98.06%) |
zero.js.br | 📈 view plot 🚷 view threshold | 50.44 KB(-0.01%)Baseline: 50.44 KB | 51.45 KB (98.03%) |
|
Branch | mlaw/rep-tx-data |
Testbed | localhost |
Click to view all benchmark results
Benchmark | Throughput | Benchmark Result operations / second (ops/s) (Result Δ%) | Lower Boundary operations / second (ops/s) (Limit %) |
---|---|---|---|
src/client/zero.bench.ts > basics > All 1000 rows x 10 columns (numbers) | 📈 view plot 🚷 view threshold | 85.90 ops/s(+12.06%)Baseline: 76.66 ops/s | 70.19 ops/s (81.71%) |
src/client/zero.bench.ts > with filter > Lower rows 500 x 10 columns (numbers) | 📈 view plot 🚷 view threshold | 108.80 ops/s(+12.94%)Baseline: 96.34 ops/s | 88.44 ops/s (81.29%) |
export interface ReplicacheOptions<MD extends MutatorDefs> { | ||
export interface ReplicacheOptions< | ||
MD extends MutatorDefs, | ||
TZeroData extends ZeroTxData = ZeroTxData, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to create a new interface that extends ReplicacheOptions. ReplicacheImpl can use that type. That way we do not have to change the public API of replicache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can either add one more option here:
mono/packages/replicache/src/replicache-impl.ts
Lines 388 to 391 in de356bd
constructor( | |
options: ReplicacheOptions<MD>, | |
implOptions: ReplicacheImplOptions = {}, | |
) { |
or you can extend ReplicacheImplOptions
which is all internal stuff the Zero and Reflect use.
export interface ReplicacheOptions<MD extends MutatorDefs> { | ||
export interface ReplicacheOptions< | ||
MD extends MutatorDefs, | ||
TZeroData extends ZeroTxData = ZeroTxData, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can either add one more option here:
mono/packages/replicache/src/replicache-impl.ts
Lines 388 to 391 in de356bd
constructor( | |
options: ReplicacheOptions<MD>, | |
implOptions: ReplicacheImplOptions = {}, | |
) { |
or you can extend ReplicacheImplOptions
which is all internal stuff the Zero and Reflect use.
*/ | ||
export type ZeroOption<T extends ZeroTxData> = { | ||
/** | ||
* Allow Zero to initialize its IVM state from the given hash and store. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
store -> dag store for clarity
* database. | ||
*/ | ||
export interface WriteTransaction extends ReadTransaction { | ||
export interface WriteTransaction<TZeroData extends ZeroTxData = ZeroTxData> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer if we do not change Replicache public types.
For Reflect we have:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have the same for Zero:
mono/packages/zero-client/src/client/custom.ts
Lines 70 to 80 in 743c954
export class TransactionImpl implements ClientTransaction<Schema> { | |
constructor(repTx: WriteTransaction, schema: Schema) { | |
must(repTx.reason === 'initial' || repTx.reason === 'rebase'); | |
this.clientID = repTx.clientID; | |
this.mutationID = repTx.mutationID; | |
this.reason = repTx.reason === 'initial' ? 'optimistic' : 'rebase'; | |
// ~ Note: we will likely need to leverage proxies one day to create | |
// ~ crud mutators and queries on demand for users with very large schemas. | |
this.mutate = makeSchemaCRUD(schema, repTx); | |
this.query = {}; | |
} |
mono/packages/zero-client/src/client/custom.ts
Lines 90 to 98 in 743c954
export function makeReplicacheMutator( | |
mutator: CustomMutatorImpl<Schema>, | |
schema: Schema, | |
) { | |
return (repTx: WriteTransaction, args: ReadonlyJSONValue): Promise<void> => { | |
const tx = new TransactionImpl(repTx, schema); | |
return mutator(tx, args); | |
}; | |
} |
but somehow we need to plumb through the correct IVM fork. Only Replicache has the information required to create that fork (base head hash, new head hash) and when to fork (when rebase begins).
} | ||
|
||
export interface WriteTransaction extends ReplicacheWriteTransaction { | ||
export interface WriteTransaction<T extends ZeroTxData = ZeroTxData> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we did this... I don't yet understand why we have to change the Replicache interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When Replicache starts a rebase it'll ask Zero (via zeroOption) to create a fork of the IVM sources at the given head. This fork will be added to WriteTransaction
so Zero
can use it in it's mutators.
Previously I assumed there were a finite (or at least small) set of heads and that Zero could look them up by name rather than having to pass the fork along in the Replicache transaction. It turns out there isn't a small set of heads being rebased onto. Looking up by name also opens us up to concurrency issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me put up the PR that actually uses this argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I see the big picture better now. I still wish we could keep the Replicache public interfaces as they are.
I have a few tricks up my sleeves that would allow this to work without changing the interface. I think it is OK to add public properties (using symbols) to the implementation without changing the interface for example. Other options include using weakmaps as sidetables.
…cache zeroOption is a minimal interface that Replicache will call when: - pullEnd - persist - refresh - mutate happen. - replicache will invoke `advance` whenever it's main head moves forward. - replicache will invoke `getTxData` to fork IVM sources whenever it needs to rebase - replicache will invoke `init` on construction to populate the IVM sources
When `zero` is running atop `replicache`, `zeroData` will be available. `zeroData` is the `IVMSourceBranch` that mutations should be using in the current transaction. It is templated here `TZeroData = unknown` so Replicache does not need to know about `IVMSourceBranch`.
4b6392e
to
f5231b4
Compare
@arv - I removed all changes to the Replicache public interface. |
well not quite. Let me try swapping that to a symbol. |
f5231b4
to
8f5799a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Thanks
zeroOption is a minimal interface that Replicache will call when:
happen. Replicache will invoke
advance
whenever it's main head moves forward.getTxData
to fork IVM sources whenever it needs to rebaseinit
on construction to populate the IVM sourcesInvoking the above three methods in
persist.ts
,refresh.ts
,replicache-impl.ts::mutate
,replicache-impl.ts::maybeEndPull
will happen in the next PR.