Skip to content

append_seen_locked reopens the dedup file and issues a redundant chmod on every persisted event, inside the write-lock critical section #322

Description

@erskingardner

Summary

On the steady-state success path, every terminally-processed event pays open + chmod + close syscalls while serialized on the dedup persistence write lock. Both are redundant.

Location

src/nostr/events/dedup.rs:246-261 (append_seen_locked), called for every processed event under write_lock at src/nostr/events/processor.rs:869-873.

Root cause

mark_seen calls append_seen_locked for every terminally-processed event while holding PersistentDedupState.write_lock. Each call:

  1. re-opens the file (OpenOptions::new().create(true).append(true).open(...) → open + eventual close), and
  2. calls tokio::fs::set_permissions(&self.path, 0o600) — a chmod syscall — on every append.

The permissions were already set to 0o600 at creation in prepare_path (dedup.rs:201-208), and create(true).append(true) on an existing file ignores the mode, so the per-append set_permissions is pure redundant work. Holding a persistent append file handle (opened once) plus a one-time chmod would remove two-to-three syscalls per processed event from the serialized critical section.

Impact

Under sustained legitimate throughput with durable dedup enabled, every processed event pays open + chmod + close while serialized on the write lock, needlessly increasing tail latency and lowering max throughput. No correctness impact.

Suggested fix

Store an already-open tokio::fs::File append handle on PersistentDedupState (created once in new/prepare_path with mode 0o600) and reuse it in append_seen_locked, dropping the per-append reopen and set_permissions.

Why this is not a duplicate

#304 concerns cleanup() holding the lock across other sweeps; #197 was the in-memory double dedup-lock on the success path. Neither addresses the per-append file reopen or the redundant chmod.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions