@fireproof/core 0.5.13 → 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/src/clock.js CHANGED
@@ -21,17 +21,17 @@ import { CIDCounter } from 'prolly-trees/utils'
21
21
 
22
22
  /**
23
23
  * @typedef {{
24
- * type: 'put'|'del'
25
- * key: string
26
- * value: import('./link').AnyLink
27
- * root: import('./link').AnyLink
28
- * }} EventData
29
- * @typedef {{
30
- * root: import('./link').AnyLink
31
- * head: import('./clock').EventLink<EventData>[]
32
- * event: import('./clock').EventBlockView<EventData>
33
- * }} Result
34
- */
24
+ * type: 'put'|'del'
25
+ * key: string
26
+ * value: import('./link').AnyLink
27
+ * root: import('./link').AnyLink
28
+ * }} EventData
29
+ * @typedef {{
30
+ * root: import('./link').AnyLink
31
+ * head: import('./clock').EventLink<EventData>[]
32
+ * event: import('./clock').EventBlockView<EventData>
33
+ * }} Result
34
+ */
35
35
 
36
36
  /**
37
37
  * Advance the clock by adding an event.
@@ -45,7 +45,7 @@ import { CIDCounter } from 'prolly-trees/utils'
45
45
  export async function advance (blocks, head, event) {
46
46
  /** @type {EventFetcher<T>} */
47
47
  const events = new EventFetcher(blocks)
48
- const headmap = new Map(head.map((cid) => [cid.toString(), cid]))
48
+ const headmap = new Map(head.map(cid => [cid.toString(), cid]))
49
49
 
50
50
  // Check if the headmap already includes the event, return head if it does
51
51
  if (headmap.has(event.toString())) return { head, cids: await events.all() }
@@ -167,14 +167,16 @@ export async function decodeEventBlock (bytes) {
167
167
  async function contains (events, a, b) {
168
168
  if (a.toString() === b.toString()) return true
169
169
  const [{ value: aevent }, { value: bevent }] = await Promise.all([events.get(a), events.get(b)])
170
- const links = [...aevent.parents]
170
+ // const links = [...aevent.parents]
171
+ // console.log('aevent', aevent.parents)
172
+ const links = [...(aevent.parents || [])]
171
173
  while (links.length) {
172
174
  const link = links.shift()
173
175
  if (!link) break
174
176
  if (link.toString() === b.toString()) return true
175
177
  // if any of b's parents are this link, then b cannot exist in any of the
176
178
  // tree below, since that would create a cycle.
177
- if (bevent.parents.some((p) => link.toString() === p.toString())) continue
179
+ if (bevent.parents.some(p => link.toString() === p.toString())) continue
178
180
  const { value: event } = await events.get(link)
179
181
  links.push(...event.parents)
180
182
  }
@@ -190,15 +192,19 @@ async function contains (events, a, b) {
190
192
  */
191
193
  export async function * vis (blocks, head, options = {}) {
192
194
  // @ts-ignore
193
- const renderNodeLabel = options.renderNodeLabel ?? ((b) => {
194
- // @ts-ignore
195
- const { key, root, type } = b.value.data
196
- return b.cid.toString() + '\n' + JSON.stringify({ key, root: root.cid.toString(), type }, null, 2).replace(/"/g, '\'')
197
- })
195
+ const renderNodeLabel =
196
+ options.renderNodeLabel ??
197
+ (b => {
198
+ // @ts-ignore
199
+ const { key, root, type } = b.value.data
200
+ return (
201
+ b.cid.toString() + '\n' + JSON.stringify({ key, root: root.cid.toString(), type }, null, 2).replace(/"/g, "'")
202
+ )
203
+ })
198
204
  const events = new EventFetcher(blocks)
199
205
  yield 'digraph clock {'
200
206
  yield ' node [shape=point fontname="Courier"]; head;'
201
- const hevents = await Promise.all(head.map((link) => events.get(link)))
207
+ const hevents = await Promise.all(head.map(link => events.get(link)))
202
208
  const links = []
203
209
  const nodes = new Set()
204
210
  for (const e of hevents) {
@@ -231,17 +237,18 @@ export async function findEventsToSync (blocks, head) {
231
237
  // console.time(callTag + '.findCommonAncestorWithSortedEvents')
232
238
  const { ancestor, sorted } = await findCommonAncestorWithSortedEvents(events, head)
233
239
  // console.timeEnd(callTag + '.findCommonAncestorWithSortedEvents')
234
- // console.log('sorted', sorted.length)
240
+ // console.log('sorted', !!ancestor, sorted.length)
235
241
  // console.time(callTag + '.contains')
236
- const toSync = await asyncFilter(sorted, async (uks) => !(await contains(events, ancestor, uks.cid)))
242
+
243
+ const toSync = ancestor ? await asyncFilter(sorted, async uks => !(await contains(events, ancestor, uks.cid))) : sorted
237
244
  // console.timeEnd(callTag + '.contains')
238
- // console.log('toSync.contains', toSync.length)
245
+ console.log('toSync', !!ancestor, sorted.length - toSync.length)
239
246
 
240
247
  return { cids: events, events: toSync }
241
248
  }
242
249
 
243
250
  const asyncFilter = async (arr, predicate) =>
244
- Promise.all(arr.map(predicate)).then((results) => arr.filter((_v, index) => results[index]))
251
+ Promise.all(arr.map(predicate)).then(results => arr.filter((_v, index) => results[index]))
245
252
 
246
253
  export async function findCommonAncestorWithSortedEvents (events, children, doFull = false) {
247
254
  // console.trace('findCommonAncestorWithSortedEvents')
@@ -252,12 +259,16 @@ export async function findCommonAncestorWithSortedEvents (events, children, doFu
252
259
  // console.timeEnd(callTag + '.findCommonAncestor')
253
260
  // console.log('ancestor', ancestor.toString())
254
261
  if (!ancestor) {
255
- throw new Error('failed to find common ancestor event')
262
+ console.log('no common ancestor', children)
263
+ // throw new Error('no common ancestor')
264
+ const sorted = await findSortedEvents(events, children, children, doFull)
265
+ return { ancestor: null, sorted }
256
266
  }
257
267
  // console.time(callTag + '.findSortedEvents')
258
- const sorted = await findSortedEvents(events, children, ancestor, doFull)
268
+ const sorted = await findSortedEvents(events, children, [ancestor], doFull)
259
269
  // console.timeEnd(callTag + '.findSortedEvents')
260
270
  // console.log('sorted', sorted.length)
271
+ // console.log('ancestor', JSON.stringify(ancestor, null, 2))
261
272
  return { ancestor, sorted }
262
273
  }
263
274
 
@@ -268,17 +279,58 @@ export async function findCommonAncestorWithSortedEvents (events, children, doFu
268
279
  * @param {import('./clock').EventFetcher} events
269
280
  * @param {import('./clock').EventLink<EventData>[]} children
270
281
  */
282
+ // async function NEWfindCommonAncestor (events, children) {
283
+ // if (!children.length) return
284
+ // if (children.length === 1) return children[0]
285
+
286
+ // const candidates = children.map(c => [c])
287
+ // const visited = new Set()
288
+
289
+ // while (true) {
290
+ // let changed = false
291
+ // for (const c of candidates) {
292
+ // const candidate = await findAncestorCandidate(events, c[c.length - 1])
293
+
294
+ // if (!candidate) continue
295
+
296
+ // if (visited.has(candidate)) {
297
+ // return candidate // Common ancestor found
298
+ // }
299
+
300
+ // visited.add(candidate)
301
+ // changed = true
302
+ // c.push(candidate)
303
+ // }
304
+
305
+ // if (!changed) {
306
+ // // No common ancestor found, exhausted candidates
307
+ // return null
308
+ // }
309
+ // }
310
+ // }
311
+
271
312
  async function findCommonAncestor (events, children) {
272
313
  if (!children.length) return
314
+ children = [...new Set(children)]
273
315
  if (children.length === 1) return children[0]
274
316
  const candidates = children.map((c) => [c])
317
+ // console.log(
318
+ // 'og candidates',
319
+ // candidates.map((c) => c.toString())
320
+ // )
275
321
  while (true) {
276
322
  let changed = false
277
323
  for (const c of candidates) {
278
324
  const candidate = await findAncestorCandidate(events, c[c.length - 1])
279
325
  if (!candidate) continue
326
+
327
+ // Check if the candidate is already in the list, and if so, skip it.
328
+ if (c.includes(candidate)) continue
329
+
330
+ // if set size is all cids, then no common ancestor
280
331
  changed = true
281
- c.push(candidate)
332
+ c.push(candidate) // make set?
333
+ // console.log('candidate', candidates.map((c) => c.toString()))
282
334
  const ancestor = findCommonString(candidates)
283
335
  if (ancestor) return ancestor
284
336
  }
@@ -286,12 +338,45 @@ async function findCommonAncestor (events, children) {
286
338
  }
287
339
  }
288
340
 
341
+ // async function OGfindCommonAncestor (events, children) {
342
+ // if (!children.length) return
343
+ // if (children.length === 1) return children[0]
344
+ // const candidates = children.map(c => [c])
345
+ // console.log(
346
+ // 'og candidates',
347
+ // candidates.map(c => c.toString())
348
+ // )
349
+ // while (true) {
350
+ // let changed = false
351
+ // for (const c of candidates) {
352
+ // const candidate = await findAncestorCandidate(events, c[c.length - 1])
353
+ // if (!candidate) continue
354
+ // // if set size is all cids, then no common ancestor
355
+ // changed = true
356
+ // c.push(candidate) // make set?
357
+ // console.log(
358
+ // 'candidate',
359
+ // candidates.map(c => c.toString())
360
+ // )
361
+ // const ancestor = findCommonString(candidates)
362
+ // if (ancestor) return ancestor
363
+ // }
364
+ // if (!changed) return
365
+ // }
366
+ // }
367
+
289
368
  /**
290
369
  * @param {import('./clock').EventFetcher} events
291
370
  * @param {import('./clock').EventLink<EventData>} root
292
371
  */
293
372
  async function findAncestorCandidate (events, root) {
294
- const { value: event } = await events.get(root)// .catch(() => ({ value: { parents: [] } }))
373
+ const { value: event } = await events.get(root) // .catch(() => ({ value: { parents: [] } }))
374
+ // console.log(
375
+ // 'findAncestorCandidate',
376
+ // root.toString(),
377
+ // 'parents',
378
+ // event.parents.map(p => p.toString())
379
+ // )
295
380
  if (!event.parents.length) return root
296
381
  return event.parents.length === 1 ? event.parents[0] : findCommonAncestor(events, event.parents)
297
382
  }
@@ -302,13 +387,13 @@ async function findAncestorCandidate (events, root) {
302
387
  */
303
388
  function findCommonString (arrays) {
304
389
  // console.log('findCommonString', arrays.map((a) => a.map((i) => String(i))))
305
- arrays = arrays.map((a) => [...a])
390
+ arrays = arrays.map(a => [...a])
306
391
  for (const arr of arrays) {
307
392
  for (const item of arr) {
308
393
  let matched = true
309
394
  for (const other of arrays) {
310
395
  if (arr === other) continue
311
- matched = other.some((i) => String(i) === String(item))
396
+ matched = other.some(i => String(i) === String(item))
312
397
  if (!matched) break
313
398
  }
314
399
  if (matched) return item
@@ -320,19 +405,19 @@ function findCommonString (arrays) {
320
405
  * Find and sort events between the head(s) and the tail.
321
406
  * @param {import('./clock').EventFetcher} events
322
407
  * @param {any[]} head
323
- * @param {import('./clock').EventLink<EventData>} tail
408
+ * @param {import('./clock').EventLink<EventData>[]} tails
324
409
  */
325
- async function findSortedEvents (events, head, tail, doFull) {
410
+ async function findSortedEvents (events, head, tails, doFull) {
326
411
  // const callTag = Math.random().toString(36).substring(7)
327
412
  // get weighted events - heavier events happened first
328
413
  // const callTag = Math.random().toString(36).substring(7)
329
414
 
330
415
  /** @type {Map<string, { event: import('./clock').EventBlockView<EventData>, weight: number }>} */
331
416
  const weights = new Map()
332
- head = [...new Set([...head.map((h) => h.toString())])]
417
+ head = [...new Set([...head.map(h => h.toString())])]
333
418
  // console.log(callTag + '.head', head.length)
334
419
 
335
- const allEvents = new Set([tail.toString(), ...head])
420
+ const allEvents = new Set([tails.map((t) => t.toString()).toString(), ...head])
336
421
  if (!doFull && allEvents.size === 1) {
337
422
  // console.log('head contains tail', tail.toString())
338
423
  return []
@@ -344,7 +429,8 @@ async function findSortedEvents (events, head, tail, doFull) {
344
429
  // console.log(callTag + '.head', head.length, [...head.map((h) => h.toString())], tail.toString())
345
430
 
346
431
  // console.time(callTag + '.findEvents')
347
- const all = await Promise.all(head.map((h) => findEvents(events, h, tail)))
432
+ const all = await (await Promise.all(tails.map((t) => Promise.all(head.map(h => findEvents(events, h, t)))))).flat()
433
+ // console.log('all', all.length)
348
434
  // console.timeEnd(callTag + '.findEvents')
349
435
  for (const arr of all) {
350
436
  for (const { event, depth } of arr) {
@@ -392,8 +478,8 @@ async function findEvents (events, start, end, depth = 0) {
392
478
  const acc = [{ event, depth }]
393
479
  const { parents } = event.value
394
480
  // if (parents.length === 1 && String(parents[0]) === send) return acc
395
- if (parents.findIndex((p) => String(p) === send) !== -1) return acc
481
+ if (parents.findIndex(p => String(p) === send) !== -1) return acc
396
482
  // if (parents.length === 1) return acc
397
- const rest = await Promise.all(parents.map((p) => findEvents(events, p, end, depth + 1)))
483
+ const rest = await Promise.all(parents.map(p => findEvents(events, p, end, depth + 1)))
398
484
  return acc.concat(...rest)
399
485
  }
package/src/crypto.js CHANGED
@@ -46,7 +46,7 @@ const decrypt = async function * ({ root, get, key, cache, chunker, hasher }) {
46
46
  const { result: nodes } = await cidset.getAllEntries()
47
47
  const unwrap = async (eblock) => {
48
48
  const { bytes, cid } = await codec.decrypt({ ...eblock, key }).catch(e => {
49
- console.log('ekey', e)
49
+ // console.log('ekey', e)
50
50
  throw new Error('bad key: ' + key.toString('hex'))
51
51
  })
52
52
  const block = await createBlock(bytes, cid)
package/src/database.js CHANGED
@@ -61,8 +61,8 @@ export class Database {
61
61
  * @memberof Fireproof
62
62
  * @instance
63
63
  */
64
- clockToJSON () {
65
- return this.clock.map(cid => cid.toString())
64
+ clockToJSON (clock = null) {
65
+ return (clock || this.clock).map(cid => cid.toString())
66
66
  }
67
67
 
68
68
  hydrate ({ clock, name, key }) {
@@ -102,21 +102,21 @@ export class Database {
102
102
  * @memberof Fireproof
103
103
  * @instance
104
104
  */
105
- async changesSince (event) {
106
- // console.log('events for', this.instanceId, event.constructor.name)
107
- // console.log('changesSince', this.instanceId, event, this.clock)
105
+ async changesSince (aClock) {
106
+ // console.log('events for', this.instanceId, aClock?.constructor.name)
107
+ // console.log('changesSince', this.instanceId, this.clockToJSON(aClock), this.clockToJSON())
108
108
  let rows, dataCIDs, clockCIDs
109
- // if (!event) event = []
110
- if (event) {
111
- event = event.map((cid) => cid.toString())
112
- const eventKey = JSON.stringify([...event, ...this.clockToJSON()])
109
+ // if (!aClock) aClock = []
110
+ if (aClock && aClock.length > 0) {
111
+ aClock = aClock.map((cid) => cid.toString())
112
+ const eventKey = JSON.stringify([...this.clockToJSON(aClock), ...this.clockToJSON()])
113
113
 
114
114
  let resp
115
115
  if (this.eventsCache.has(eventKey)) {
116
- console.log('events from cache')
116
+ // console.log('events from cache')
117
117
  resp = this.eventsCache.get(eventKey)
118
118
  } else {
119
- resp = await eventsSince(this.blocks, this.clock, event)
119
+ resp = await eventsSince(this.blocks, this.clock, aClock)
120
120
  this.eventsCache.set(eventKey, resp)
121
121
  }
122
122
  const docsMap = new Map()
@@ -277,7 +277,9 @@ export class Database {
277
277
  */
278
278
  async putToProllyTree (decodedEvent, clock = null) {
279
279
  const event = encodeEvent(decodedEvent)
280
- if (clock && JSON.stringify(clock) !== JSON.stringify(this.clockToJSON())) {
280
+ if (clock && JSON.stringify(this.clockToJSON(clock)) !== JSON.stringify(this.clockToJSON())) {
281
+ // console.log('this.clock', this.clockToJSON())
282
+ // console.log('that.clock', this.clockToJSON(clock))
281
283
  // we need to check and see what version of the document exists at the clock specified
282
284
  // if it is the same as the one we are trying to put, then we can proceed
283
285
  const resp = await eventsSince(this.blocks, this.clock, event.value._clock)
@@ -287,6 +289,7 @@ export class Database {
287
289
  }
288
290
  }
289
291
  const prevClock = [...this.clock]
292
+ // console.log('putToProllyTree', this.clockToJSON(), decodedEvent)
290
293
  const result = await doTransaction(
291
294
  'putToProllyTree',
292
295
  this.blocks,
package/src/db-index.js CHANGED
@@ -351,7 +351,7 @@ export class DbIndex {
351
351
  )
352
352
  this.indexByKey = await bulkIndex(blocks, this.indexByKey, oldIndexEntries.concat(indexEntries), dbIndexOpts)
353
353
  this.dbHead = result.clock
354
- })
354
+ }, false /* don't sync transaction -- maybe move this flag to database.indexBlocks? */)
355
355
  // todo index subscriptions
356
356
  // this.database.notifyExternal('dbIndex')
357
357
  // console.timeEnd(callTag + '.doTransactionupdateIndex')
package/src/prolly.js CHANGED
@@ -19,6 +19,8 @@ import { doTransaction } from './blockstore.js'
19
19
  import { create as createBlock } from 'multiformats/block'
20
20
  const blockOpts = { cache, chunker: bf(30), codec, hasher, compare }
21
21
 
22
+ // const SYNC_ROOT = 'fireproof' // change this if you want to break sync
23
+
22
24
  /**
23
25
  * @typedef {import('./blockstore.js').TransactionBlockstore} TransactionBlockstore
24
26
  */
@@ -52,13 +54,11 @@ export const makeGetBlock = blocks => {
52
54
  async function createAndSaveNewEvent ({ inBlocks, bigPut, root, event: inEvent, head, additions, removals = [] }) {
53
55
  let cids
54
56
  const { key, value, del } = inEvent
57
+ // console.log('createAndSaveNewEvent', root.constructor.name, root.entryList)
58
+ // root = await root.block
55
59
  const data = {
56
60
  root: root
57
- ? {
58
- cid: root.cid,
59
- bytes: root.bytes, // can we remove this?
60
- value: root.value // can we remove this?
61
- }
61
+ ? (await root.address)
62
62
  : null,
63
63
  key
64
64
  }
@@ -70,6 +70,29 @@ async function createAndSaveNewEvent ({ inBlocks, bigPut, root, event: inEvent,
70
70
  data.value = value
71
71
  data.type = 'put'
72
72
  }
73
+ // console.log('head', head)
74
+ // if (head.length === 0) {
75
+ // // create an empty prolly root
76
+ // let emptyRoot
77
+
78
+ // for await (const node of create({ get: getBlock, list: [{ key: '_sync', value: SYNC_ROOT }], ...blockOpts })) {
79
+ // emptyRoot = await node.block
80
+ // bigPut(emptyRoot)
81
+ // }
82
+ // console.log('emptyRoot', emptyRoot)
83
+ // const first = await EventBlock.create(
84
+ // {
85
+ // root: emptyRoot.cid,
86
+ // key: null,
87
+ // value: null,
88
+ // type: 'del'
89
+ // },
90
+ // []
91
+ // )
92
+ // bigPut(first)
93
+ // head = [first.cid]
94
+ // }
95
+
73
96
  /** @type {import('./clock').EventData} */
74
97
  // @ts-ignore
75
98
  const event = await EventBlock.create(data, head)
@@ -138,16 +161,23 @@ const prollyRootFromAncestor = async (events, ancestor, getBlock) => {
138
161
  // console.log('prollyRootFromAncestor', ancestor)
139
162
  const event = await events.get(ancestor)
140
163
  const { root } = event.value.data
141
- // console.log('prollyRootFromAncestor', root.cid, JSON.stringify(root.value))
142
164
  if (root) {
143
- return load({ cid: root.cid, get: getBlock, ...blockOpts })
165
+ return load({ cid: root, get: getBlock, ...blockOpts })
144
166
  } else {
145
- return null
167
+ // console.log('no root', root) // false means no common ancestor. null means empty database.
168
+ return root
146
169
  }
147
170
  }
148
171
 
172
+ // async function bigMerge (events, head, getBlock) {
173
+ // const allRoots = await Promise.all(head.map(async h => prollyRootFromAncestor(events, h, getBlock)))
174
+ // console.log('allRoots', allRoots)
175
+ // // todo query over all roots and merge them, but how do they not have a common ancestor? they all start with the _sync root
176
+ // throw new Error('not implemented')
177
+ // }
178
+
149
179
  const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
150
- const { getBlock, blocks } = makeGetAndPutBlock(inBlocks)
180
+ const { getBlock, blocks } = makeGetAndPutBlock(inBlocks) // this is doubled with eventfetcher
151
181
  let bulkSorted = []
152
182
  let prollyRootNode = null
153
183
  const events = new EventFetcher(blocks)
@@ -155,14 +185,22 @@ const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
155
185
  if (!doFull && head.length === 1) {
156
186
  prollyRootNode = await prollyRootFromAncestor(events, head[0], getBlock)
157
187
  } else {
158
- // Otherwise, we find the common ancestor and update the root and other blocks
159
- // todo this is returning more events than necessary, lets define the desired semantics from the top down
160
- // good semantics mean we can cache the results of this call
188
+ // Otherwise, we find the common ancestor and update the root and other blocks
189
+ // todo this is returning more events than necessary, lets define the desired semantics from the top down
190
+ // good semantics mean we can cache the results of this call
191
+ // const {cids, events : bulkSorted } = await findEventsToSync(blocks, head)
161
192
  const { ancestor, sorted } = await findCommonAncestorWithSortedEvents(events, head, doFull)
193
+
162
194
  bulkSorted = sorted
163
- // console.log('sorted', JSON.stringify(sorted.map(({ value: { data: { key, value } } }) => ({ key, value }))))
164
- prollyRootNode = await prollyRootFromAncestor(events, ancestor, getBlock)
165
- // console.log('event', event)
195
+ // console.log('sorted', !!ancestor, JSON.stringify(sorted.map(({ value: { data: { key, value } } }) => ({ key, value }))))
196
+ if (ancestor) {
197
+ prollyRootNode = await prollyRootFromAncestor(events, ancestor, getBlock)
198
+ // if (!prollyRootNode) {
199
+ // prollyRootNode = await bigMerge(events, head, getBlock)
200
+ // // throw new Error('no common ancestor')
201
+ // }
202
+ }
203
+ // console.log('event', event)
166
204
  }
167
205
  }
168
206
 
@@ -170,16 +208,23 @@ const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
170
208
 
171
209
  // if prolly root node is null, we need to create a new one
172
210
  if (!prollyRootNode) {
211
+ // console.log('make new root', bulkOperations.length)
173
212
  let root
213
+ // let rootNode
174
214
  const newBlocks = []
175
215
  // if all operations are deletes, we can just return an empty root
176
216
  if (bulkOperations.every(op => op.del)) {
177
217
  return { root: null, blocks: [], clockCIDs: await events.all() }
178
218
  }
179
219
  for await (const node of create({ get: getBlock, list: bulkOperations, ...blockOpts })) {
180
- root = await node.block
181
- newBlocks.push(root)
220
+ // root = await node.block
221
+ root = node
222
+ newBlocks.push(await node.block)
182
223
  }
224
+ // throw new Error('not root time')
225
+ // root.isThisOne = 'yes'
226
+ // console.log('made new root', root.constructor.name, root.block.cid.toString())
227
+
183
228
  return { root, blocks: newBlocks, clockCIDs: await events.all() }
184
229
  } else {
185
230
  const writeResp = await prollyRootNode.bulk(bulkOperations) // { root: newProllyRootNode, blocks: newBlocks }
@@ -199,7 +244,7 @@ const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
199
244
  */
200
245
  export async function put (inBlocks, head, event, options) {
201
246
  const { bigPut } = makeGetAndPutBlock(inBlocks)
202
-
247
+ // console.log('major put')
203
248
  // If the head is empty, we create a new event and return the root and addition blocks
204
249
  if (!head.length) {
205
250
  const additions = new Map()
@@ -231,7 +276,7 @@ export async function put (inBlocks, head, event, options) {
231
276
  return createAndSaveNewEvent({
232
277
  inBlocks,
233
278
  bigPut,
234
- root: prollyRootBlock,
279
+ root: newProllyRootNode, // Block
235
280
  event,
236
281
  head,
237
282
  additions: Array.from(additions.values()) /*, todo? Array.from(removals.values()) */
@@ -250,20 +295,25 @@ export async function root (inBlocks, head, doFull = false) {
250
295
  throw new Error('no head')
251
296
  }
252
297
  // console.log('root', head.map(h => h.toString()))
253
- const { root: newProllyRootNode, blocks: newBlocks, clockCIDs } = await doProllyBulk(inBlocks, head, null, doFull)
254
298
  // todo maybe these should go to a temp blockstore?
255
- await doTransaction(
299
+ return await doTransaction(
256
300
  'root',
257
301
  inBlocks,
258
302
  async transactionBlocks => {
259
303
  const { bigPut } = makeGetAndPutBlock(transactionBlocks)
304
+ const { root: newProllyRootNode, blocks: newBlocks, clockCIDs } = await doProllyBulk(inBlocks, head, null, doFull)
305
+ //
306
+ // const rootBlock = await newProllyRootNode.block
307
+ // bigPut(rootBlock)
260
308
  for (const nb of newBlocks) {
261
309
  bigPut(nb)
262
310
  }
311
+ // console.log('root root', newProllyRootNode.constructor.name, newProllyRootNode)
312
+ return { clockCIDs, node: newProllyRootNode }
263
313
  },
264
314
  false
265
315
  )
266
- return { clockCIDs, node: newProllyRootNode }
316
+ // return { clockCIDs, node: newProllyRootNode }
267
317
  }
268
318
 
269
319
  /**
@@ -279,7 +329,8 @@ export async function eventsSince (blocks, head, since) {
279
329
  return { clockCIDs: [], result: [] }
280
330
  }
281
331
  // @ts-ignore
282
- const sinceHead = [...since, ...head] // ?
332
+ const sinceHead = [...since, ...head].map(h => h.toString()) // ?
333
+ // console.log('eventsSince', sinceHead.map(h => h.toString()))
283
334
  const { cids, events: unknownSorted3 } = await findEventsToSync(blocks, sinceHead)
284
335
  return { clockCIDs: cids, result: unknownSorted3.map(({ value: { data } }) => data) }
285
336
  }
@@ -318,9 +369,16 @@ async function rootOrCache (blocks, head, rootCache, doFull = false) {
318
369
  // console.log('finding root')
319
370
  // const callTag = Math.random().toString(36).substring(7)
320
371
  // console.time(callTag + '.root')
372
+ //
373
+ // const prevClock = [...this.clock]
374
+
321
375
  ;({ node, clockCIDs } = await root(blocks, head, doFull))
376
+
377
+ // this.applyClock(prevClock, result.head)
378
+ // await this.notifyListeners([decodedEvent])
379
+
322
380
  // console.timeEnd(callTag + '.root')
323
- // console.log('found root')
381
+ // console.log('found root', node.entryList)
324
382
  }
325
383
  return { node, clockCIDs }
326
384
  }
package/src/sync.js CHANGED
@@ -23,10 +23,15 @@ export class Sync {
23
23
  this.pushBacklogResolve = resolve
24
24
  this.pushBacklogReject = reject
25
25
  })
26
+ this.isReady = false
26
27
  // this.pushBacklog.then(() => {
27
28
  // // console.log('sync backlog resolved')
28
29
  // this.database.notifyReset()
29
30
  // })
31
+ // this.connected = new Promise((resolve, reject) => {
32
+ // this.readyResolve = resolve
33
+ // this.readyReject = reject
34
+ // })
30
35
  }
31
36
 
32
37
  async offer () {
@@ -75,22 +80,22 @@ export class Sync {
75
80
  // console.log('not a car', data.toString())
76
81
  }
77
82
  if (reader) {
78
- console.log('got car')
83
+ // console.log('got car')
79
84
  this.status = 'parking car'
80
85
  const blz = new Set()
81
86
  for await (const block of reader.blocks()) {
82
87
  blz.add(block)
83
88
  }
84
89
  const roots = await reader.getRoots()
85
- console.log(
86
- 'got car',
87
- roots.map(c => c.toString()),
88
- this.database.clock.map(c => c.toString())
89
- )
90
- console.log(
91
- 'got blocks',
92
- [...blz].map(({ cid }) => cid.toString())
93
- )
90
+ // console.log(
91
+ // 'got car',
92
+ // roots.map(c => c.toString()),
93
+ // this.database.clock.map(c => c.toString())
94
+ // )
95
+ // console.log(
96
+ // 'got blocks!',
97
+ // [...blz].map(({ cid }) => cid.toString())
98
+ // )
94
99
  // @ts-ignore
95
100
  reader.entries = reader.blocks
96
101
  await this.database.blocks.commit(
@@ -129,7 +134,7 @@ export class Sync {
129
134
  } else if (message.clock) {
130
135
  const reqCidDiff = message
131
136
  // this might be a CID diff
132
- console.log('got diff', reqCidDiff)
137
+ // console.log('got diff', reqCidDiff)
133
138
  const carBlock = await Sync.makeCar(this.database, null, reqCidDiff.cids)
134
139
  if (!carBlock) {
135
140
  // we are full synced
@@ -138,9 +143,10 @@ export class Sync {
138
143
  this.peer.send(JSON.stringify({ ok: true }))
139
144
  // this.pushBacklogResolve({ ok: true })
140
145
  } else {
141
- console.log('do send', carBlock.bytes.length)
146
+ // console.log('do send diff', carBlock.bytes.length)
142
147
  this.status = 'sending diff car'
143
148
  this.peer.send(carBlock.bytes)
149
+ // console.log('sent diff car')
144
150
  // this.pushBacklogResolve({ ok: true })
145
151
  }
146
152
  }
@@ -154,7 +160,7 @@ export class Sync {
154
160
  }
155
161
 
156
162
  async sendUpdate (blockstore) {
157
- if (!this.peer) return
163
+ if (!this.peer || !this.isReady) return
158
164
  // console.log('send update from', this.database.instanceId)
159
165
  // todo should send updates since last sync
160
166
  const newCar = await blocksToCarBlock(blockstore.lastCid, blockstore)
@@ -164,6 +170,7 @@ export class Sync {
164
170
 
165
171
  async startSync () {
166
172
  // console.log('start sync', this.peer.initiator)
173
+ this.isReady = true
167
174
  const allCIDs = await this.database.allStoredCIDs()
168
175
  // console.log('allCIDs', allCIDs)
169
176
  const reqCidDiff = {