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