@fireproof/core 0.5.12 → 0.5.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/use-fireproof.js +2 -1
- package/dist/src/blockstore.js +4 -4
- package/dist/src/clock.js +109 -37
- package/dist/src/crypto.js +1 -1
- package/dist/src/database.js +20 -19
- package/dist/src/db-index.js +6 -6
- package/dist/src/fireproof.d.ts +3 -2
- package/dist/src/fireproof.js +238 -85
- package/dist/src/fireproof.js.map +1 -1
- package/dist/src/fireproof.mjs +238 -85
- package/dist/src/fireproof.mjs.map +1 -1
- package/dist/src/listener.js +2 -3
- package/dist/src/prolly.js +74 -25
- package/dist/src/sha1.js +2 -1
- package/dist/src/sync.js +28 -9
- package/dist/src/valet.js +5 -1
- package/package.json +2 -2
- package/src/blockstore.js +1 -0
- package/src/clock.js +123 -37
- package/src/crypto.js +1 -1
- package/src/database.js +15 -12
- package/src/db-index.js +1 -1
- package/src/prolly.js +82 -24
- package/src/sync.js +12 -4
- package/src/valet.js +5 -5
package/dist/src/fireproof.js
CHANGED
@@ -5499,17 +5499,17 @@ class CIDCounter {
|
|
5499
5499
|
|
5500
5500
|
/**
|
5501
5501
|
* @typedef {{
|
5502
|
-
* type: 'put'|'del'
|
5503
|
-
* key: string
|
5504
|
-
* value: import('./link').AnyLink
|
5505
|
-
* root: import('./link').AnyLink
|
5506
|
-
* }} EventData
|
5507
|
-
* @typedef {{
|
5508
|
-
* root: import('./link').AnyLink
|
5509
|
-
* head: import('./clock').EventLink<EventData>[]
|
5510
|
-
* event: import('./clock').EventBlockView<EventData>
|
5511
|
-
* }} Result
|
5512
|
-
*/
|
5502
|
+
* type: 'put'|'del'
|
5503
|
+
* key: string
|
5504
|
+
* value: import('./link').AnyLink
|
5505
|
+
* root: import('./link').AnyLink
|
5506
|
+
* }} EventData
|
5507
|
+
* @typedef {{
|
5508
|
+
* root: import('./link').AnyLink
|
5509
|
+
* head: import('./clock').EventLink<EventData>[]
|
5510
|
+
* event: import('./clock').EventBlockView<EventData>
|
5511
|
+
* }} Result
|
5512
|
+
*/
|
5513
5513
|
|
5514
5514
|
/**
|
5515
5515
|
* Advance the clock by adding an event.
|
@@ -5523,7 +5523,7 @@ class CIDCounter {
|
|
5523
5523
|
async function advance (blocks, head, event) {
|
5524
5524
|
/** @type {EventFetcher<T>} */
|
5525
5525
|
const events = new EventFetcher(blocks);
|
5526
|
-
const headmap = new Map(head.map(
|
5526
|
+
const headmap = new Map(head.map(cid => [cid.toString(), cid]));
|
5527
5527
|
|
5528
5528
|
// Check if the headmap already includes the event, return head if it does
|
5529
5529
|
if (headmap.has(event.toString())) return { head, cids: await events.all() }
|
@@ -5645,14 +5645,16 @@ async function decodeEventBlock (bytes) {
|
|
5645
5645
|
async function contains (events, a, b) {
|
5646
5646
|
if (a.toString() === b.toString()) return true
|
5647
5647
|
const [{ value: aevent }, { value: bevent }] = await Promise.all([events.get(a), events.get(b)]);
|
5648
|
-
const links = [...aevent.parents]
|
5648
|
+
// const links = [...aevent.parents]
|
5649
|
+
// console.log('aevent', aevent.parents)
|
5650
|
+
const links = [...(aevent.parents || [])];
|
5649
5651
|
while (links.length) {
|
5650
5652
|
const link = links.shift();
|
5651
5653
|
if (!link) break
|
5652
5654
|
if (link.toString() === b.toString()) return true
|
5653
5655
|
// if any of b's parents are this link, then b cannot exist in any of the
|
5654
5656
|
// tree below, since that would create a cycle.
|
5655
|
-
if (bevent.parents.some(
|
5657
|
+
if (bevent.parents.some(p => link.toString() === p.toString())) continue
|
5656
5658
|
const { value: event } = await events.get(link);
|
5657
5659
|
links.push(...event.parents);
|
5658
5660
|
}
|
@@ -5668,15 +5670,19 @@ async function contains (events, a, b) {
|
|
5668
5670
|
*/
|
5669
5671
|
async function * vis$1 (blocks, head, options = {}) {
|
5670
5672
|
// @ts-ignore
|
5671
|
-
const renderNodeLabel =
|
5672
|
-
|
5673
|
-
|
5674
|
-
|
5675
|
-
|
5673
|
+
const renderNodeLabel =
|
5674
|
+
options.renderNodeLabel ??
|
5675
|
+
(b => {
|
5676
|
+
// @ts-ignore
|
5677
|
+
const { key, root, type } = b.value.data;
|
5678
|
+
return (
|
5679
|
+
b.cid.toString() + '\n' + JSON.stringify({ key, root: root.cid.toString(), type }, null, 2).replace(/"/g, "'")
|
5680
|
+
)
|
5681
|
+
});
|
5676
5682
|
const events = new EventFetcher(blocks);
|
5677
5683
|
yield 'digraph clock {';
|
5678
5684
|
yield ' node [shape=point fontname="Courier"]; head;';
|
5679
|
-
const hevents = await Promise.all(head.map(
|
5685
|
+
const hevents = await Promise.all(head.map(link => events.get(link)));
|
5680
5686
|
const links = [];
|
5681
5687
|
const nodes = new Set();
|
5682
5688
|
for (const e of hevents) {
|
@@ -5709,17 +5715,18 @@ async function findEventsToSync (blocks, head) {
|
|
5709
5715
|
// console.time(callTag + '.findCommonAncestorWithSortedEvents')
|
5710
5716
|
const { ancestor, sorted } = await findCommonAncestorWithSortedEvents(events, head);
|
5711
5717
|
// console.timeEnd(callTag + '.findCommonAncestorWithSortedEvents')
|
5712
|
-
// console.log('sorted', sorted.length)
|
5718
|
+
// console.log('sorted', !!ancestor, sorted.length)
|
5713
5719
|
// console.time(callTag + '.contains')
|
5714
|
-
|
5720
|
+
|
5721
|
+
const toSync = ancestor ? await asyncFilter(sorted, async uks => !(await contains(events, ancestor, uks.cid))) : sorted;
|
5715
5722
|
// console.timeEnd(callTag + '.contains')
|
5716
|
-
|
5723
|
+
console.log('toSync', !!ancestor, sorted.length - toSync.length);
|
5717
5724
|
|
5718
5725
|
return { cids: events, events: toSync }
|
5719
5726
|
}
|
5720
5727
|
|
5721
5728
|
const asyncFilter = async (arr, predicate) =>
|
5722
|
-
Promise.all(arr.map(predicate)).then(
|
5729
|
+
Promise.all(arr.map(predicate)).then(results => arr.filter((_v, index) => results[index]));
|
5723
5730
|
|
5724
5731
|
async function findCommonAncestorWithSortedEvents (events, children, doFull = false) {
|
5725
5732
|
// console.trace('findCommonAncestorWithSortedEvents')
|
@@ -5730,12 +5737,16 @@ async function findCommonAncestorWithSortedEvents (events, children, doFull = fa
|
|
5730
5737
|
// console.timeEnd(callTag + '.findCommonAncestor')
|
5731
5738
|
// console.log('ancestor', ancestor.toString())
|
5732
5739
|
if (!ancestor) {
|
5733
|
-
|
5740
|
+
console.log('no common ancestor', children);
|
5741
|
+
// throw new Error('no common ancestor')
|
5742
|
+
const sorted = await findSortedEvents(events, children, children, doFull);
|
5743
|
+
return { ancestor: null, sorted }
|
5734
5744
|
}
|
5735
5745
|
// console.time(callTag + '.findSortedEvents')
|
5736
|
-
const sorted = await findSortedEvents(events, children, ancestor, doFull);
|
5746
|
+
const sorted = await findSortedEvents(events, children, [ancestor], doFull);
|
5737
5747
|
// console.timeEnd(callTag + '.findSortedEvents')
|
5738
5748
|
// console.log('sorted', sorted.length)
|
5749
|
+
// console.log('ancestor', JSON.stringify(ancestor, null, 2))
|
5739
5750
|
return { ancestor, sorted }
|
5740
5751
|
}
|
5741
5752
|
|
@@ -5746,17 +5757,58 @@ async function findCommonAncestorWithSortedEvents (events, children, doFull = fa
|
|
5746
5757
|
* @param {import('./clock').EventFetcher} events
|
5747
5758
|
* @param {import('./clock').EventLink<EventData>[]} children
|
5748
5759
|
*/
|
5760
|
+
// async function NEWfindCommonAncestor (events, children) {
|
5761
|
+
// if (!children.length) return
|
5762
|
+
// if (children.length === 1) return children[0]
|
5763
|
+
|
5764
|
+
// const candidates = children.map(c => [c])
|
5765
|
+
// const visited = new Set()
|
5766
|
+
|
5767
|
+
// while (true) {
|
5768
|
+
// let changed = false
|
5769
|
+
// for (const c of candidates) {
|
5770
|
+
// const candidate = await findAncestorCandidate(events, c[c.length - 1])
|
5771
|
+
|
5772
|
+
// if (!candidate) continue
|
5773
|
+
|
5774
|
+
// if (visited.has(candidate)) {
|
5775
|
+
// return candidate // Common ancestor found
|
5776
|
+
// }
|
5777
|
+
|
5778
|
+
// visited.add(candidate)
|
5779
|
+
// changed = true
|
5780
|
+
// c.push(candidate)
|
5781
|
+
// }
|
5782
|
+
|
5783
|
+
// if (!changed) {
|
5784
|
+
// // No common ancestor found, exhausted candidates
|
5785
|
+
// return null
|
5786
|
+
// }
|
5787
|
+
// }
|
5788
|
+
// }
|
5789
|
+
|
5749
5790
|
async function findCommonAncestor (events, children) {
|
5750
5791
|
if (!children.length) return
|
5792
|
+
children = [...new Set(children)];
|
5751
5793
|
if (children.length === 1) return children[0]
|
5752
5794
|
const candidates = children.map((c) => [c]);
|
5795
|
+
// console.log(
|
5796
|
+
// 'og candidates',
|
5797
|
+
// candidates.map((c) => c.toString())
|
5798
|
+
// )
|
5753
5799
|
while (true) {
|
5754
5800
|
let changed = false;
|
5755
5801
|
for (const c of candidates) {
|
5756
5802
|
const candidate = await findAncestorCandidate(events, c[c.length - 1]);
|
5757
5803
|
if (!candidate) continue
|
5804
|
+
|
5805
|
+
// Check if the candidate is already in the list, and if so, skip it.
|
5806
|
+
if (c.includes(candidate)) continue
|
5807
|
+
|
5808
|
+
// if set size is all cids, then no common ancestor
|
5758
5809
|
changed = true;
|
5759
|
-
c.push(candidate);
|
5810
|
+
c.push(candidate); // make set?
|
5811
|
+
// console.log('candidate', candidates.map((c) => c.toString()))
|
5760
5812
|
const ancestor = findCommonString(candidates);
|
5761
5813
|
if (ancestor) return ancestor
|
5762
5814
|
}
|
@@ -5764,12 +5816,45 @@ async function findCommonAncestor (events, children) {
|
|
5764
5816
|
}
|
5765
5817
|
}
|
5766
5818
|
|
5819
|
+
// async function OGfindCommonAncestor (events, children) {
|
5820
|
+
// if (!children.length) return
|
5821
|
+
// if (children.length === 1) return children[0]
|
5822
|
+
// const candidates = children.map(c => [c])
|
5823
|
+
// console.log(
|
5824
|
+
// 'og candidates',
|
5825
|
+
// candidates.map(c => c.toString())
|
5826
|
+
// )
|
5827
|
+
// while (true) {
|
5828
|
+
// let changed = false
|
5829
|
+
// for (const c of candidates) {
|
5830
|
+
// const candidate = await findAncestorCandidate(events, c[c.length - 1])
|
5831
|
+
// if (!candidate) continue
|
5832
|
+
// // if set size is all cids, then no common ancestor
|
5833
|
+
// changed = true
|
5834
|
+
// c.push(candidate) // make set?
|
5835
|
+
// console.log(
|
5836
|
+
// 'candidate',
|
5837
|
+
// candidates.map(c => c.toString())
|
5838
|
+
// )
|
5839
|
+
// const ancestor = findCommonString(candidates)
|
5840
|
+
// if (ancestor) return ancestor
|
5841
|
+
// }
|
5842
|
+
// if (!changed) return
|
5843
|
+
// }
|
5844
|
+
// }
|
5845
|
+
|
5767
5846
|
/**
|
5768
5847
|
* @param {import('./clock').EventFetcher} events
|
5769
5848
|
* @param {import('./clock').EventLink<EventData>} root
|
5770
5849
|
*/
|
5771
5850
|
async function findAncestorCandidate (events, root) {
|
5772
|
-
const { value: event } = await events.get(root)
|
5851
|
+
const { value: event } = await events.get(root); // .catch(() => ({ value: { parents: [] } }))
|
5852
|
+
// console.log(
|
5853
|
+
// 'findAncestorCandidate',
|
5854
|
+
// root.toString(),
|
5855
|
+
// 'parents',
|
5856
|
+
// event.parents.map(p => p.toString())
|
5857
|
+
// )
|
5773
5858
|
if (!event.parents.length) return root
|
5774
5859
|
return event.parents.length === 1 ? event.parents[0] : findCommonAncestor(events, event.parents)
|
5775
5860
|
}
|
@@ -5780,13 +5865,13 @@ async function findAncestorCandidate (events, root) {
|
|
5780
5865
|
*/
|
5781
5866
|
function findCommonString (arrays) {
|
5782
5867
|
// console.log('findCommonString', arrays.map((a) => a.map((i) => String(i))))
|
5783
|
-
arrays = arrays.map(
|
5868
|
+
arrays = arrays.map(a => [...a]);
|
5784
5869
|
for (const arr of arrays) {
|
5785
5870
|
for (const item of arr) {
|
5786
5871
|
let matched = true;
|
5787
5872
|
for (const other of arrays) {
|
5788
5873
|
if (arr === other) continue
|
5789
|
-
matched = other.some(
|
5874
|
+
matched = other.some(i => String(i) === String(item));
|
5790
5875
|
if (!matched) break
|
5791
5876
|
}
|
5792
5877
|
if (matched) return item
|
@@ -5798,19 +5883,19 @@ function findCommonString (arrays) {
|
|
5798
5883
|
* Find and sort events between the head(s) and the tail.
|
5799
5884
|
* @param {import('./clock').EventFetcher} events
|
5800
5885
|
* @param {any[]} head
|
5801
|
-
* @param {import('./clock').EventLink<EventData>}
|
5886
|
+
* @param {import('./clock').EventLink<EventData>[]} tails
|
5802
5887
|
*/
|
5803
|
-
async function findSortedEvents (events, head,
|
5888
|
+
async function findSortedEvents (events, head, tails, doFull) {
|
5804
5889
|
// const callTag = Math.random().toString(36).substring(7)
|
5805
5890
|
// get weighted events - heavier events happened first
|
5806
5891
|
// const callTag = Math.random().toString(36).substring(7)
|
5807
5892
|
|
5808
5893
|
/** @type {Map<string, { event: import('./clock').EventBlockView<EventData>, weight: number }>} */
|
5809
5894
|
const weights = new Map();
|
5810
|
-
head = [...new Set([...head.map(
|
5895
|
+
head = [...new Set([...head.map(h => h.toString())])];
|
5811
5896
|
// console.log(callTag + '.head', head.length)
|
5812
5897
|
|
5813
|
-
const allEvents = new Set([
|
5898
|
+
const allEvents = new Set([tails.map((t) => t.toString()).toString(), ...head]);
|
5814
5899
|
if (!doFull && allEvents.size === 1) {
|
5815
5900
|
// console.log('head contains tail', tail.toString())
|
5816
5901
|
return []
|
@@ -5822,7 +5907,8 @@ async function findSortedEvents (events, head, tail, doFull) {
|
|
5822
5907
|
// console.log(callTag + '.head', head.length, [...head.map((h) => h.toString())], tail.toString())
|
5823
5908
|
|
5824
5909
|
// console.time(callTag + '.findEvents')
|
5825
|
-
const all = await Promise.all(
|
5910
|
+
const all = await (await Promise.all(tails.map((t) => Promise.all(head.map(h => findEvents(events, h, t)))))).flat();
|
5911
|
+
// console.log('all', all.length)
|
5826
5912
|
// console.timeEnd(callTag + '.findEvents')
|
5827
5913
|
for (const arr of all) {
|
5828
5914
|
for (const { event, depth } of arr) {
|
@@ -5870,9 +5956,9 @@ async function findEvents (events, start, end, depth = 0) {
|
|
5870
5956
|
const acc = [{ event, depth }];
|
5871
5957
|
const { parents } = event.value;
|
5872
5958
|
// if (parents.length === 1 && String(parents[0]) === send) return acc
|
5873
|
-
if (parents.findIndex(
|
5959
|
+
if (parents.findIndex(p => String(p) === send) !== -1) return acc
|
5874
5960
|
// if (parents.length === 1) return acc
|
5875
|
-
const rest = await Promise.all(parents.map(
|
5961
|
+
const rest = await Promise.all(parents.map(p => findEvents(events, p, end, depth + 1)));
|
5876
5962
|
return acc.concat(...rest)
|
5877
5963
|
}
|
5878
5964
|
|
@@ -36828,7 +36914,7 @@ const decrypt = async function * ({ root, get, key, cache, chunker, hasher }) {
|
|
36828
36914
|
const { result: nodes } = await cidset.getAllEntries();
|
36829
36915
|
const unwrap = async (eblock) => {
|
36830
36916
|
const { bytes, cid } = await decrypt$1({ ...eblock, key }).catch(e => {
|
36831
|
-
console.log('ekey', e)
|
36917
|
+
// console.log('ekey', e)
|
36832
36918
|
throw new Error('bad key: ' + key.toString('hex'))
|
36833
36919
|
});
|
36834
36920
|
const block = await createBlock(bytes, cid);
|
@@ -36949,11 +37035,11 @@ class Valet {
|
|
36949
37035
|
this.name = name;
|
36950
37036
|
this.setKeyMaterial(keyMaterial);
|
36951
37037
|
this.uploadQueue = cargoQueue(async (tasks, callback) => {
|
36952
|
-
console.log(
|
36953
|
-
|
36954
|
-
|
36955
|
-
|
36956
|
-
)
|
37038
|
+
// console.log(
|
37039
|
+
// 'queue worker',
|
37040
|
+
// tasks.length,
|
37041
|
+
// tasks.reduce((acc, t) => acc + t.value.length, 0)
|
37042
|
+
// )
|
36957
37043
|
if (this.uploadFunction) {
|
36958
37044
|
// todo we can coalesce these into a single car file
|
36959
37045
|
return await this.withDB(async db => {
|
@@ -37375,6 +37461,7 @@ class TransactionBlockstore {
|
|
37375
37461
|
await this.doCommit(innerBlockstore);
|
37376
37462
|
if (doSync) {
|
37377
37463
|
// const all =
|
37464
|
+
// console.log('syncing', innerBlockstore.label)
|
37378
37465
|
await Promise.all([...this.syncs].map(async sync => sync.sendUpdate(innerBlockstore).catch(e => {
|
37379
37466
|
console.error('sync error, cancelling', e);
|
37380
37467
|
sync.destroy();
|
@@ -37487,6 +37574,8 @@ class InnerBlockstore {
|
|
37487
37574
|
|
37488
37575
|
const blockOpts = { cache: nocache, chunker: bf(30), codec: codec$1, hasher: sha256$2, compare: simpleCompare };
|
37489
37576
|
|
37577
|
+
// const SYNC_ROOT = 'fireproof' // change this if you want to break sync
|
37578
|
+
|
37490
37579
|
/**
|
37491
37580
|
* @typedef {import('./blockstore.js').TransactionBlockstore} TransactionBlockstore
|
37492
37581
|
*/
|
@@ -37520,13 +37609,11 @@ const makeGetBlock = blocks => {
|
|
37520
37609
|
async function createAndSaveNewEvent ({ inBlocks, bigPut, root, event: inEvent, head, additions, removals = [] }) {
|
37521
37610
|
let cids;
|
37522
37611
|
const { key, value, del } = inEvent;
|
37612
|
+
// console.log('createAndSaveNewEvent', root.constructor.name, root.entryList)
|
37613
|
+
// root = await root.block
|
37523
37614
|
const data = {
|
37524
37615
|
root: root
|
37525
|
-
?
|
37526
|
-
cid: root.cid,
|
37527
|
-
bytes: root.bytes, // can we remove this?
|
37528
|
-
value: root.value // can we remove this?
|
37529
|
-
}
|
37616
|
+
? (await root.address)
|
37530
37617
|
: null,
|
37531
37618
|
key
|
37532
37619
|
};
|
@@ -37538,6 +37625,29 @@ async function createAndSaveNewEvent ({ inBlocks, bigPut, root, event: inEvent,
|
|
37538
37625
|
data.value = value;
|
37539
37626
|
data.type = 'put';
|
37540
37627
|
}
|
37628
|
+
// console.log('head', head)
|
37629
|
+
// if (head.length === 0) {
|
37630
|
+
// // create an empty prolly root
|
37631
|
+
// let emptyRoot
|
37632
|
+
|
37633
|
+
// for await (const node of create({ get: getBlock, list: [{ key: '_sync', value: SYNC_ROOT }], ...blockOpts })) {
|
37634
|
+
// emptyRoot = await node.block
|
37635
|
+
// bigPut(emptyRoot)
|
37636
|
+
// }
|
37637
|
+
// console.log('emptyRoot', emptyRoot)
|
37638
|
+
// const first = await EventBlock.create(
|
37639
|
+
// {
|
37640
|
+
// root: emptyRoot.cid,
|
37641
|
+
// key: null,
|
37642
|
+
// value: null,
|
37643
|
+
// type: 'del'
|
37644
|
+
// },
|
37645
|
+
// []
|
37646
|
+
// )
|
37647
|
+
// bigPut(first)
|
37648
|
+
// head = [first.cid]
|
37649
|
+
// }
|
37650
|
+
|
37541
37651
|
/** @type {import('./clock').EventData} */
|
37542
37652
|
// @ts-ignore
|
37543
37653
|
const event = await EventBlock.create(data, head);
|
@@ -37606,16 +37716,23 @@ const prollyRootFromAncestor = async (events, ancestor, getBlock) => {
|
|
37606
37716
|
// console.log('prollyRootFromAncestor', ancestor)
|
37607
37717
|
const event = await events.get(ancestor);
|
37608
37718
|
const { root } = event.value.data;
|
37609
|
-
// console.log('prollyRootFromAncestor', root.cid, JSON.stringify(root.value))
|
37610
37719
|
if (root) {
|
37611
|
-
return load$2({ cid: root
|
37720
|
+
return load$2({ cid: root, get: getBlock, ...blockOpts })
|
37612
37721
|
} else {
|
37613
|
-
|
37722
|
+
// console.log('no root', root) // false means no common ancestor. null means empty database.
|
37723
|
+
return root
|
37614
37724
|
}
|
37615
37725
|
};
|
37616
37726
|
|
37727
|
+
// async function bigMerge (events, head, getBlock) {
|
37728
|
+
// const allRoots = await Promise.all(head.map(async h => prollyRootFromAncestor(events, h, getBlock)))
|
37729
|
+
// console.log('allRoots', allRoots)
|
37730
|
+
// // todo query over all roots and merge them, but how do they not have a common ancestor? they all start with the _sync root
|
37731
|
+
// throw new Error('not implemented')
|
37732
|
+
// }
|
37733
|
+
|
37617
37734
|
const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
|
37618
|
-
const { getBlock, blocks } = makeGetAndPutBlock(inBlocks);
|
37735
|
+
const { getBlock, blocks } = makeGetAndPutBlock(inBlocks); // this is doubled with eventfetcher
|
37619
37736
|
let bulkSorted = [];
|
37620
37737
|
let prollyRootNode = null;
|
37621
37738
|
const events = new EventFetcher(blocks);
|
@@ -37623,14 +37740,22 @@ const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
|
|
37623
37740
|
if (!doFull && head.length === 1) {
|
37624
37741
|
prollyRootNode = await prollyRootFromAncestor(events, head[0], getBlock);
|
37625
37742
|
} else {
|
37626
|
-
|
37627
|
-
|
37628
|
-
|
37743
|
+
// Otherwise, we find the common ancestor and update the root and other blocks
|
37744
|
+
// todo this is returning more events than necessary, lets define the desired semantics from the top down
|
37745
|
+
// good semantics mean we can cache the results of this call
|
37746
|
+
// const {cids, events : bulkSorted } = await findEventsToSync(blocks, head)
|
37629
37747
|
const { ancestor, sorted } = await findCommonAncestorWithSortedEvents(events, head, doFull);
|
37748
|
+
|
37630
37749
|
bulkSorted = sorted;
|
37631
|
-
// console.log('sorted', JSON.stringify(sorted.map(({ value: { data: { key, value } } }) => ({ key, value }))))
|
37632
|
-
|
37633
|
-
|
37750
|
+
// console.log('sorted', !!ancestor, JSON.stringify(sorted.map(({ value: { data: { key, value } } }) => ({ key, value }))))
|
37751
|
+
if (ancestor) {
|
37752
|
+
prollyRootNode = await prollyRootFromAncestor(events, ancestor, getBlock);
|
37753
|
+
// if (!prollyRootNode) {
|
37754
|
+
// prollyRootNode = await bigMerge(events, head, getBlock)
|
37755
|
+
// // throw new Error('no common ancestor')
|
37756
|
+
// }
|
37757
|
+
}
|
37758
|
+
// console.log('event', event)
|
37634
37759
|
}
|
37635
37760
|
}
|
37636
37761
|
|
@@ -37638,16 +37763,23 @@ const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
|
|
37638
37763
|
|
37639
37764
|
// if prolly root node is null, we need to create a new one
|
37640
37765
|
if (!prollyRootNode) {
|
37766
|
+
// console.log('make new root', bulkOperations.length)
|
37641
37767
|
let root;
|
37768
|
+
// let rootNode
|
37642
37769
|
const newBlocks = [];
|
37643
37770
|
// if all operations are deletes, we can just return an empty root
|
37644
37771
|
if (bulkOperations.every(op => op.del)) {
|
37645
37772
|
return { root: null, blocks: [], clockCIDs: await events.all() }
|
37646
37773
|
}
|
37647
37774
|
for await (const node of create$3({ get: getBlock, list: bulkOperations, ...blockOpts })) {
|
37648
|
-
root = await node.block
|
37649
|
-
|
37775
|
+
// root = await node.block
|
37776
|
+
root = node;
|
37777
|
+
newBlocks.push(await node.block);
|
37650
37778
|
}
|
37779
|
+
// throw new Error('not root time')
|
37780
|
+
// root.isThisOne = 'yes'
|
37781
|
+
// console.log('made new root', root.constructor.name, root.block.cid.toString())
|
37782
|
+
|
37651
37783
|
return { root, blocks: newBlocks, clockCIDs: await events.all() }
|
37652
37784
|
} else {
|
37653
37785
|
const writeResp = await prollyRootNode.bulk(bulkOperations); // { root: newProllyRootNode, blocks: newBlocks }
|
@@ -37667,7 +37799,7 @@ const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
|
|
37667
37799
|
*/
|
37668
37800
|
async function put (inBlocks, head, event, options) {
|
37669
37801
|
const { bigPut } = makeGetAndPutBlock(inBlocks);
|
37670
|
-
|
37802
|
+
// console.log('major put')
|
37671
37803
|
// If the head is empty, we create a new event and return the root and addition blocks
|
37672
37804
|
if (!head.length) {
|
37673
37805
|
const additions = new Map();
|
@@ -37699,7 +37831,7 @@ async function put (inBlocks, head, event, options) {
|
|
37699
37831
|
return createAndSaveNewEvent({
|
37700
37832
|
inBlocks,
|
37701
37833
|
bigPut,
|
37702
|
-
root:
|
37834
|
+
root: newProllyRootNode, // Block
|
37703
37835
|
event,
|
37704
37836
|
head,
|
37705
37837
|
additions: Array.from(additions.values()) /*, todo? Array.from(removals.values()) */
|
@@ -37718,20 +37850,25 @@ async function root (inBlocks, head, doFull = false) {
|
|
37718
37850
|
throw new Error('no head')
|
37719
37851
|
}
|
37720
37852
|
// console.log('root', head.map(h => h.toString()))
|
37721
|
-
const { root: newProllyRootNode, blocks: newBlocks, clockCIDs } = await doProllyBulk(inBlocks, head, null, doFull);
|
37722
37853
|
// todo maybe these should go to a temp blockstore?
|
37723
|
-
await doTransaction(
|
37854
|
+
return await doTransaction(
|
37724
37855
|
'root',
|
37725
37856
|
inBlocks,
|
37726
37857
|
async transactionBlocks => {
|
37727
37858
|
const { bigPut } = makeGetAndPutBlock(transactionBlocks);
|
37859
|
+
const { root: newProllyRootNode, blocks: newBlocks, clockCIDs } = await doProllyBulk(inBlocks, head, null, doFull);
|
37860
|
+
//
|
37861
|
+
// const rootBlock = await newProllyRootNode.block
|
37862
|
+
// bigPut(rootBlock)
|
37728
37863
|
for (const nb of newBlocks) {
|
37729
37864
|
bigPut(nb);
|
37730
37865
|
}
|
37866
|
+
// console.log('root root', newProllyRootNode.constructor.name, newProllyRootNode)
|
37867
|
+
return { clockCIDs, node: newProllyRootNode }
|
37731
37868
|
},
|
37732
37869
|
false
|
37733
|
-
)
|
37734
|
-
return { clockCIDs, node: newProllyRootNode }
|
37870
|
+
)
|
37871
|
+
// return { clockCIDs, node: newProllyRootNode }
|
37735
37872
|
}
|
37736
37873
|
|
37737
37874
|
/**
|
@@ -37747,7 +37884,8 @@ async function eventsSince (blocks, head, since) {
|
|
37747
37884
|
return { clockCIDs: [], result: [] }
|
37748
37885
|
}
|
37749
37886
|
// @ts-ignore
|
37750
|
-
const sinceHead = [...since, ...head]; // ?
|
37887
|
+
const sinceHead = [...since, ...head].map(h => h.toString()); // ?
|
37888
|
+
// console.log('eventsSince', sinceHead.map(h => h.toString()))
|
37751
37889
|
const { cids, events: unknownSorted3 } = await findEventsToSync(blocks, sinceHead);
|
37752
37890
|
return { clockCIDs: cids, result: unknownSorted3.map(({ value: { data } }) => data) }
|
37753
37891
|
}
|
@@ -37784,8 +37922,12 @@ async function rootOrCache (blocks, head, rootCache, doFull = false) {
|
|
37784
37922
|
clockCIDs = rootCache.clockCIDs;
|
37785
37923
|
} else {
|
37786
37924
|
({ node, clockCIDs } = await root(blocks, head, doFull));
|
37925
|
+
|
37926
|
+
// this.applyClock(prevClock, result.head)
|
37927
|
+
// await this.notifyListeners([decodedEvent])
|
37928
|
+
|
37787
37929
|
// console.timeEnd(callTag + '.root')
|
37788
|
-
// console.log('found root')
|
37930
|
+
// console.log('found root', node.entryList)
|
37789
37931
|
}
|
37790
37932
|
return { node, clockCIDs }
|
37791
37933
|
}
|
@@ -38153,8 +38295,8 @@ class Database {
|
|
38153
38295
|
* @memberof Fireproof
|
38154
38296
|
* @instance
|
38155
38297
|
*/
|
38156
|
-
clockToJSON () {
|
38157
|
-
return this.clock.map(cid => cid.toString())
|
38298
|
+
clockToJSON (clock = null) {
|
38299
|
+
return (clock || this.clock).map(cid => cid.toString())
|
38158
38300
|
}
|
38159
38301
|
|
38160
38302
|
hydrate ({ clock, name, key }) {
|
@@ -38194,21 +38336,21 @@ class Database {
|
|
38194
38336
|
* @memberof Fireproof
|
38195
38337
|
* @instance
|
38196
38338
|
*/
|
38197
|
-
async changesSince (
|
38198
|
-
// console.log('events for', this.instanceId,
|
38199
|
-
// console.log('changesSince', this.instanceId,
|
38339
|
+
async changesSince (aClock) {
|
38340
|
+
// console.log('events for', this.instanceId, aClock?.constructor.name)
|
38341
|
+
// console.log('changesSince', this.instanceId, this.clockToJSON(aClock), this.clockToJSON())
|
38200
38342
|
let rows, dataCIDs, clockCIDs;
|
38201
|
-
// if (!
|
38202
|
-
if (
|
38203
|
-
|
38204
|
-
const eventKey = JSON.stringify([...
|
38343
|
+
// if (!aClock) aClock = []
|
38344
|
+
if (aClock && aClock.length > 0) {
|
38345
|
+
aClock = aClock.map((cid) => cid.toString());
|
38346
|
+
const eventKey = JSON.stringify([...this.clockToJSON(aClock), ...this.clockToJSON()]);
|
38205
38347
|
|
38206
38348
|
let resp;
|
38207
38349
|
if (this.eventsCache.has(eventKey)) {
|
38208
|
-
console.log('events from cache')
|
38350
|
+
// console.log('events from cache')
|
38209
38351
|
resp = this.eventsCache.get(eventKey);
|
38210
38352
|
} else {
|
38211
|
-
resp = await eventsSince(this.blocks, this.clock,
|
38353
|
+
resp = await eventsSince(this.blocks, this.clock, aClock);
|
38212
38354
|
this.eventsCache.set(eventKey, resp);
|
38213
38355
|
}
|
38214
38356
|
const docsMap = new Map();
|
@@ -38369,7 +38511,9 @@ class Database {
|
|
38369
38511
|
*/
|
38370
38512
|
async putToProllyTree (decodedEvent, clock = null) {
|
38371
38513
|
const event = encodeEvent(decodedEvent);
|
38372
|
-
if (clock && JSON.stringify(clock) !== JSON.stringify(this.clockToJSON())) {
|
38514
|
+
if (clock && JSON.stringify(this.clockToJSON(clock)) !== JSON.stringify(this.clockToJSON())) {
|
38515
|
+
// console.log('this.clock', this.clockToJSON())
|
38516
|
+
// console.log('that.clock', this.clockToJSON(clock))
|
38373
38517
|
// we need to check and see what version of the document exists at the clock specified
|
38374
38518
|
// if it is the same as the one we are trying to put, then we can proceed
|
38375
38519
|
const resp = await eventsSince(this.blocks, this.clock, event.value._clock);
|
@@ -38379,6 +38523,7 @@ class Database {
|
|
38379
38523
|
}
|
38380
38524
|
}
|
38381
38525
|
const prevClock = [...this.clock];
|
38526
|
+
// console.log('putToProllyTree', this.clockToJSON(), decodedEvent)
|
38382
38527
|
const result = await doTransaction(
|
38383
38528
|
'putToProllyTree',
|
38384
38529
|
this.blocks,
|
@@ -39068,7 +39213,7 @@ class DbIndex {
|
|
39068
39213
|
);
|
39069
39214
|
this.indexByKey = await bulkIndex(blocks, this.indexByKey, oldIndexEntries.concat(indexEntries), dbIndexOpts);
|
39070
39215
|
this.dbHead = result.clock;
|
39071
|
-
});
|
39216
|
+
}, false /* don't sync transaction -- maybe move this flag to database.indexBlocks? */);
|
39072
39217
|
// todo index subscriptions
|
39073
39218
|
// this.database.notifyExternal('dbIndex')
|
39074
39219
|
// console.timeEnd(callTag + '.doTransactionupdateIndex')
|
@@ -41023,10 +41168,15 @@ class Sync {
|
|
41023
41168
|
this.pushBacklogResolve = resolve;
|
41024
41169
|
this.pushBacklogReject = reject;
|
41025
41170
|
});
|
41171
|
+
this.isReady = false;
|
41026
41172
|
// this.pushBacklog.then(() => {
|
41027
41173
|
// // console.log('sync backlog resolved')
|
41028
41174
|
// this.database.notifyReset()
|
41029
41175
|
// })
|
41176
|
+
// this.connected = new Promise((resolve, reject) => {
|
41177
|
+
// this.readyResolve = resolve
|
41178
|
+
// this.readyReject = reject
|
41179
|
+
// })
|
41030
41180
|
}
|
41031
41181
|
|
41032
41182
|
async offer () {
|
@@ -41075,6 +41225,7 @@ class Sync {
|
|
41075
41225
|
// console.log('not a car', data.toString())
|
41076
41226
|
}
|
41077
41227
|
if (reader) {
|
41228
|
+
// console.log('got car')
|
41078
41229
|
this.status = 'parking car';
|
41079
41230
|
const blz = new Set();
|
41080
41231
|
for await (const block of reader.blocks()) {
|
@@ -41087,7 +41238,7 @@ class Sync {
|
|
41087
41238
|
// this.database.clock.map(c => c.toString())
|
41088
41239
|
// )
|
41089
41240
|
// console.log(
|
41090
|
-
// 'got blocks',
|
41241
|
+
// 'got blocks!',
|
41091
41242
|
// [...blz].map(({ cid }) => cid.toString())
|
41092
41243
|
// )
|
41093
41244
|
// @ts-ignore
|
@@ -41128,7 +41279,7 @@ class Sync {
|
|
41128
41279
|
} else if (message.clock) {
|
41129
41280
|
const reqCidDiff = message;
|
41130
41281
|
// this might be a CID diff
|
41131
|
-
console.log('got diff', reqCidDiff)
|
41282
|
+
// console.log('got diff', reqCidDiff)
|
41132
41283
|
const carBlock = await Sync.makeCar(this.database, null, reqCidDiff.cids);
|
41133
41284
|
if (!carBlock) {
|
41134
41285
|
// we are full synced
|
@@ -41137,9 +41288,10 @@ class Sync {
|
|
41137
41288
|
this.peer.send(JSON.stringify({ ok: true }));
|
41138
41289
|
// this.pushBacklogResolve({ ok: true })
|
41139
41290
|
} else {
|
41140
|
-
// console.log('do send', carBlock.bytes.length)
|
41291
|
+
// console.log('do send diff', carBlock.bytes.length)
|
41141
41292
|
this.status = 'sending diff car';
|
41142
41293
|
this.peer.send(carBlock.bytes);
|
41294
|
+
// console.log('sent diff car')
|
41143
41295
|
// this.pushBacklogResolve({ ok: true })
|
41144
41296
|
}
|
41145
41297
|
}
|
@@ -41153,7 +41305,7 @@ class Sync {
|
|
41153
41305
|
}
|
41154
41306
|
|
41155
41307
|
async sendUpdate (blockstore) {
|
41156
|
-
if (!this.peer) return
|
41308
|
+
if (!this.peer || !this.isReady) return
|
41157
41309
|
// console.log('send update from', this.database.instanceId)
|
41158
41310
|
// todo should send updates since last sync
|
41159
41311
|
const newCar = await blocksToCarBlock(blockstore.lastCid, blockstore);
|
@@ -41163,6 +41315,7 @@ class Sync {
|
|
41163
41315
|
|
41164
41316
|
async startSync () {
|
41165
41317
|
// console.log('start sync', this.peer.initiator)
|
41318
|
+
this.isReady = true;
|
41166
41319
|
const allCIDs = await this.database.allStoredCIDs();
|
41167
41320
|
// console.log('allCIDs', allCIDs)
|
41168
41321
|
const reqCidDiff = {
|