From c4fd63239fdd9e5a1d1a71d4ed8c1b869177794c Mon Sep 17 00:00:00 2001 From: Andre Staltz Date: Thu, 26 Oct 2023 11:14:02 +0300 Subject: [PATCH] getMsgPurpose returns also details alongside purpose tag --- lib/index.js | 22 ++++++++++++++-------- test/goals.test.js | 27 +++++++++++++++++---------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/lib/index.js b/lib/index.js index 1823af6..d7be9fd 100644 --- a/lib/index.js +++ b/lib/index.js @@ -13,6 +13,7 @@ const Obz = require('obz') * @typedef {'none'|'all'|'newest'|'record'|'set'} GoalType * @typedef {[number, number]} Range * @typedef {{ id: string, type: GoalType, count: number }} Goal + * @typedef {{ tangleID: MsgID, span: number }} GhostDetails */ /** @@ -39,7 +40,11 @@ const Obz = require('obz') * These tags are ordered, "none" < "ghost" < "trail" < "goal", meaning that a * msg with purpose "goal" may *also* fulfill the purpose of "trail", and a * "trail" also prevents accidental re-request like "ghost" does. - * @typedef {'none' | 'ghost' | 'trail' | 'goal'} Purpose + * @typedef {['none'] + * | ['ghost', GhostDetails] + * | ['trail'] + * | ['goal'] + * } PurposeWithDetails */ /** @@ -194,7 +199,7 @@ function initGoals(peer, config) { * @public * @param {MsgID} msgID * @param {Msg} msg - * @returns {Purpose} + * @returns {PurposeWithDetails} */ function getMsgPurpose(msgID, msg) { assertDBPlugin(peer) @@ -208,7 +213,7 @@ function initGoals(peer, config) { if (!tangle) break asRoot const [min, max] = crossGoalWithTangle(goal, tangle) if (min > max) break asRoot - if (min === 0) return 'goal' + if (min === 0) return ['goal'] if (min > 0) servesAsTrail = true } @@ -229,11 +234,11 @@ function initGoals(peer, config) { } // (Loop over once without heavy computations and maybe return early:) for (const [, min, max, recDepth] of validTangles) { - if (min <= recDepth && recDepth <= max) return 'goal' + if (min <= recDepth && recDepth <= max) return ['goal'] } // At this point we know that the record *cannot* serve as 'goal', // so if it serves as trail, that'll do: - if (servesAsTrail) return 'trail' + if (servesAsTrail) return ['trail'] // Check whether this record is a trail affix of some tangle: // (Loop again with heavy computations now that it's inevitable:) for (const [tangle, min] of validTangles) { @@ -241,20 +246,21 @@ function initGoals(peer, config) { .topoSort() .filter((msgID) => tangle.getDepth(msgID) === min) const { erasables } = tangle.getDeletablesAndErasables(...minMsgIDs) - if (erasables.has(msgID)) return 'trail' + if (erasables.has(msgID)) return ['trail'] } // Check whether this record is a ghost affix of some tangle: for (const [tangle, , , , goalType] of validTangles) { if (goalType === 'record') { assertRecordPlugin(peer) + const span = peer.record.getGhostSpan() if (peer.record.isGhostable(msgID, tangle.id)) { - return 'ghost' + return ['ghost', {tangleID: tangle.id, span }] } } } - return 'none' + return ['none'] } /** diff --git a/test/goals.test.js b/test/goals.test.js index e57833e..2a6bb59 100644 --- a/test/goals.test.js +++ b/test/goals.test.js @@ -34,7 +34,10 @@ test('set, getByID, list, listen', async (t) => { } { - const purpose = alice.goals.getMsgPurpose(aliceAccountRoot.id, aliceAccountRoot.msg) + const [purpose] = alice.goals.getMsgPurpose( + aliceAccountRoot.id, + aliceAccountRoot.msg + ) assert.equal(purpose, 'goal', 'rec purpose is "goal"') } @@ -91,19 +94,19 @@ test('getMsgPurpose', async (t) => { const gottenGoal = alice.goals.get(feedID) assert.strictEqual(gottenGoal.id, feedID, 'gotten goal id is correct') - const purpose = alice.goals.getMsgPurpose(post2.id, post2.msg) + const [purpose] = alice.goals.getMsgPurpose(post2.id, post2.msg) assert.equal(purpose, 'goal', 'purpose is "goal"') alice.goals.set(feedID, 'newest-1') assert('set goal to newest-1') - const purpose2 = alice.goals.getMsgPurpose(post2.id, post2.msg) + const [purpose2] = alice.goals.getMsgPurpose(post2.id, post2.msg) assert.equal(purpose2, 'none', 'purpose2 is "none"') await p(alice.close)(true) }) test('getMsgPurpose ghost', async (t) => { - const alice = createPeer({ name: 'alice', record: {ghostSpan: 3} }) + const alice = createPeer({ name: 'alice', record: { ghostSpan: 3 } }) await alice.db.loaded() const aliceID = await p(alice.db.account.create)({ @@ -123,14 +126,18 @@ test('getMsgPurpose ghost', async (t) => { const msgIDs = tangle.topoSort() assert.equal(msgIDs.length, 6, 'tangle has root+5 messages') - const recs = msgIDs.map(id => alice.db.getRecord(id)) + const recs = msgIDs.map((id) => alice.db.getRecord(id)) alice.goals.set(feedID, 'record') - assert.equal(alice.goals.getMsgPurpose(recs[1].id, recs[1].msg), 'none') - assert.equal(alice.goals.getMsgPurpose(recs[2].id, recs[2].msg), 'ghost') - assert.equal(alice.goals.getMsgPurpose(recs[3].id, recs[3].msg), 'trail') - assert.equal(alice.goals.getMsgPurpose(recs[4].id, recs[4].msg), 'trail') - assert.equal(alice.goals.getMsgPurpose(recs[5].id, recs[5].msg), 'goal') + assert.equal(alice.goals.getMsgPurpose(recs[1].id, recs[1].msg)[0], 'none') + assert.equal(alice.goals.getMsgPurpose(recs[2].id, recs[2].msg)[0], 'ghost') + assert.equal(alice.goals.getMsgPurpose(recs[3].id, recs[3].msg)[0], 'trail') + assert.equal(alice.goals.getMsgPurpose(recs[4].id, recs[4].msg)[0], 'trail') + assert.equal(alice.goals.getMsgPurpose(recs[5].id, recs[5].msg)[0], 'goal') + + const [purpose, details] = alice.goals.getMsgPurpose(recs[2].id, recs[2].msg) + assert.equal(purpose, 'ghost') + assert.deepEqual(details, { tangleID: feedID, span: 3 }) await p(alice.close)(true) })