Files
psf-memo/psf-memo-db/test/unit/lib/backfill-profile-recency.unit.js
T
Chris Troutner bdf2c3015e Implement profile ordering by last post
Indexer: maintain a profileRecency index keyed by address with the newest
confirmed qualifying post (top-level 0x6d02 or topic message 0x6d0c).
Replies and poll creations do not qualify, and mempool (unconfirmed) posts do
not write the index. Setting a profile after posting establishes recency from
the address's existing addrPostHeights, excluding replies and polls.

DB: GET /profile/recent now orders profiles by their most recent qualifying
post (height desc, seen desc, address asc) from profileRecency plus per-page
profile lookups, so it no longer scans addrPostHeights or sorts the whole
profiles store. Add a profileRecency backfill library and CLI that rebuilds
the index from addrPostHeights, posts, postParents, polls, and status,
ignoring unconfirmed entries and removing stale records.

Add focused unit tests, acceptance fixtures, and regex step handlers.

By coder.
2026-09-20 14:36:08 -07:00

105 lines
3.6 KiB
JavaScript

import { assert } from 'chai'
import { backfillProfileRecency, partsFromAddrPostHeightKey } from '../../../src/lib/backfill-profile-recency.js'
import { FakeDb } from '../../support/level-double.js'
const ALICE = 'bitcoincash:qaddr-alice'
const BOB = 'bitcoincash:qaddr-bob'
const NOPOST = 'bitcoincash:qaddr-nopost'
function pad (height) {
return String(height).padStart(12, '0')
}
function addrPostHeightKey (addr, height, txid) {
return `${addr}:${pad(height)}:${txid}`
}
function fixtureStores () {
const profilesDb = new FakeDb([
[ALICE, { text: 'alice bio', txid: 'profile-alice' }],
[BOB, { text: 'bob bio', txid: 'profile-bob' }],
[NOPOST, { text: 'nopost bio', txid: 'profile-nopost' }]
])
const postsDb = new FakeDb([
['post-a1', { addr: ALICE, seen: 100, blockHeight: 600100 }],
['reply-a1', { addr: ALICE, seen: 150, blockHeight: 600300 }],
['post-b1', { addr: BOB, seen: 200, blockHeight: 600400 }],
['post-b2', { addr: BOB, seen: 250, blockHeight: 600500 }]
])
const addrPostHeightsDb = new FakeDb([
[addrPostHeightKey(ALICE, 600100, 'post-a1'), { txid: 'post-a1', addr: ALICE, blockHeight: 600100 }],
[addrPostHeightKey(ALICE, 600300, 'reply-a1'), { txid: 'reply-a1', addr: ALICE, blockHeight: 600300 }],
[addrPostHeightKey(ALICE, 600200, 'poll-a1'), { txid: 'poll-a1', addr: ALICE, blockHeight: 600200 }],
[addrPostHeightKey(BOB, 600400, 'post-b1'), { txid: 'post-b1', addr: BOB, blockHeight: 600400 }],
[addrPostHeightKey(BOB, 600500, 'post-b2'), { txid: 'post-b2', addr: BOB, blockHeight: 600500 }]
])
const postParentsDb = new FakeDb([
['reply-a1', { txid: 'reply-a1', parentTxid: 'post-a1' }]
])
const pollsDb = new FakeDb([
['poll-a1', { txid: 'poll-a1' }]
])
const statusDb = new FakeDb([
['status', { chainBlockHeight: 600450 }]
])
const profileRecencyDb = new FakeDb()
return { profilesDb, postsDb, addrPostHeightsDb, postParentsDb, pollsDb, statusDb, profileRecencyDb }
}
describe('#backfillProfileRecency', () => {
it('should record each profile newest confirmed qualifying post', async () => {
const stores = fixtureStores()
const result = await backfillProfileRecency(stores)
assert.equal(result.profiles, 2)
assert.deepEqual(stores.profileRecencyDb.store.get(ALICE), {
addr: ALICE, blockHeight: 600100, seen: 100
})
assert.deepEqual(stores.profileRecencyDb.store.get(BOB), {
addr: BOB, blockHeight: 600400, seen: 200
})
})
it('should not record a profile with no qualifying post', async () => {
const stores = fixtureStores()
await backfillProfileRecency(stores)
assert.isFalse(stores.profileRecencyDb.store.has(NOPOST))
})
it('should be idempotent', async () => {
const stores = fixtureStores()
await backfillProfileRecency(stores)
const afterFirst = new Map(stores.profileRecencyDb.store)
await backfillProfileRecency(stores)
assert.deepEqual(stores.profileRecencyDb.store, afterFirst)
})
it('should remove stale recency records for addresses that no longer qualify', async () => {
const stores = fixtureStores()
stores.profileRecencyDb.put(NOPOST, { addr: NOPOST, blockHeight: 600900, seen: 9 })
await backfillProfileRecency(stores)
assert.isFalse(stores.profileRecencyDb.store.has(NOPOST))
})
})
describe('#partsFromAddrPostHeightKey', () => {
it('should recover the address, height, and txid from a key', () => {
assert.deepEqual(partsFromAddrPostHeightKey(addrPostHeightKey(ALICE, 600100, 'post-a1')), {
addr: ALICE,
blockHeight: 600100,
txid: 'post-a1'
})
})
})