Skip to content

fix(3393): Ensure channel deletions are honored - #3401

Merged
islathehut merged 9 commits into
9.0.0from
fix/3393-deletions-not-propagating
Aug 5, 2026
Merged

fix(3393): Ensure channel deletions are honored#3401
islathehut merged 9 commits into
9.0.0from
fix/3393-deletions-not-propagating

Conversation

@islathehut

@islathehut islathehut commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Pull Request Checklist

  • I have linked this PR to a related GitHub issue.
  • I have added a description of the change (and Github issue number, if any) to the root CHANGELOG.md.

(Optional) Mobile checklist

Please ensure you completed the following checks if you did any changes to the mobile package:

  • I have run e2e tests for mobile
  • I have updated base screenshots for visual regression tests

@islathehut islathehut linked an issue Aug 3, 2026 that may be closed by this pull request
@islathehut
islathehut requested a review from adrastaea August 3, 2026 19:52
Comment on lines +76 to +112
@@ -87,17 +93,23 @@ const Index =
for await (const entry of log.traverse(null, shoudStopTraverse)) {
const { hash, payload } = entry
// If an entry is not yet indexed, process it
if (await isNotIndexed(hash)) {
const isHashNotIndexed = await isNotIndexed(hash)
if (isHashNotIndexed) {
const { op, key } = payload
const isValid = validateFn ? await validateFn(entry) : true
if (op === 'PUT' && !keys.has(key) && isValid) {
keys.add(key)
await index.put(key as string, encodeEntry(entry))
if (op === OrbitDbOp.PUT && isValid) {
const isKeyDeleted = await isDeleted(key!)
if (!keys.has(key) && !isKeyDeleted) {
keys.add(key)
await index.put(key as string, encodeEntry(entry))
await indexedKeysWithOp.put(key as string, OrbitDbOp.PUT)
}
await indexedEntries.put(hash, true)
} else if (op === 'DEL' && !keys.has(key) && isValid) {
} else if (op === OrbitDbOp.DEL && isValid) {
keys.add(key)
await index.del(key as string)
await indexedEntries.put(hash, true)
await indexedKeysWithOp.put(key as string, OrbitDbOp.DEL)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the fix. Basically when the deletions were processed we would skip over marking the put hashes as indexed and that resulted in future reindexing treating them as fresh puts since the check for an entry being indexed is based on the hash.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there may be an issue with this though that will cause PUT("key", "old value") -> DEL ("key") -> PUT("key", "new value") to result in the key to still be indexed as deleted because we are storing the deletion of key persistently and skipping processing the new PUT because it was previously deleted. You can add

  it('allows a newer PUT to recreate a deleted key', async () => {
    orbitDbService = await module.resolve(OrbitDbService)
    await orbitDbService.create(ipfsService.ipfsInstance!)

    const store = await orbitDbService.open<KeyValueIndexedValidatedType<string>>(
      `recreated-key-test-store-${Date.now()}`,
      {
        Database: KeyValueIndexedValidated(),
        AccessController: IPFSAccessController({ write: ['*'] }),
        sync: false,
      }
    )

    await store.put('key', 'old value')
    await store.del('key')
    await store.put('key', 'new value')

    await expect(store.get('key')).resolves.toBe('new value')
  })

to the orbitdb service tests to prove this.

Comment on lines +76 to +112
@@ -87,17 +93,23 @@ const Index =
for await (const entry of log.traverse(null, shoudStopTraverse)) {
const { hash, payload } = entry
// If an entry is not yet indexed, process it
if (await isNotIndexed(hash)) {
const isHashNotIndexed = await isNotIndexed(hash)
if (isHashNotIndexed) {
const { op, key } = payload
const isValid = validateFn ? await validateFn(entry) : true
if (op === 'PUT' && !keys.has(key) && isValid) {
keys.add(key)
await index.put(key as string, encodeEntry(entry))
if (op === OrbitDbOp.PUT && isValid) {
const isKeyDeleted = await isDeleted(key!)
if (!keys.has(key) && !isKeyDeleted) {
keys.add(key)
await index.put(key as string, encodeEntry(entry))
await indexedKeysWithOp.put(key as string, OrbitDbOp.PUT)
}
await indexedEntries.put(hash, true)
} else if (op === 'DEL' && !keys.has(key) && isValid) {
} else if (op === OrbitDbOp.DEL && isValid) {
keys.add(key)
await index.del(key as string)
await indexedEntries.put(hash, true)
await indexedKeysWithOp.put(key as string, OrbitDbOp.DEL)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there may be an issue with this though that will cause PUT("key", "old value") -> DEL ("key") -> PUT("key", "new value") to result in the key to still be indexed as deleted because we are storing the deletion of key persistently and skipping processing the new PUT because it was previously deleted. You can add

  it('allows a newer PUT to recreate a deleted key', async () => {
    orbitDbService = await module.resolve(OrbitDbService)
    await orbitDbService.create(ipfsService.ipfsInstance!)

    const store = await orbitDbService.open<KeyValueIndexedValidatedType<string>>(
      `recreated-key-test-store-${Date.now()}`,
      {
        Database: KeyValueIndexedValidated(),
        AccessController: IPFSAccessController({ write: ['*'] }),
        sync: false,
      }
    )

    await store.put('key', 'old value')
    await store.del('key')
    await store.put('key', 'new value')

    await expect(store.get('key')).resolves.toBe('new value')
  })

to the orbitdb service tests to prove this.

@islathehut islathehut changed the title Fix/3393 deletions not propagating fix(3393): Ensure channel deletions are honored Aug 4, 2026
@islathehut
islathehut merged commit 85366a2 into 9.0.0 Aug 5, 2026
37 of 39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deleting channels on the Tor version is syncing poorly

2 participants