Skip to content

Conversation

@alltheseas
Copy link
Collaborator

Summary

fixes kingcache media/image cache clearing bug

image

Checklist

  • I have read (or I am familiar with) the Contribution Guidelines
  • I have tested the changes in this PR - *only in Xcode iOS Simulator
  • I have profiled the changes to ensure there are no performance regressions, or I do not need to profile the changes.
  • I have opened or referred to an existing github issue related to this change: Double-check why kingfisher isn't clearing #2861
  • My PR is either small, or I have split it into smaller logical commits that are easier to review
  • I have added the signoff line to all my commits. See Signing off your work
  • I have added appropriate changelog entries for the changes in this PR. See Adding changelog entries
    • I do not need to add a changelog entry. Reason: [Please provide a reason]
  • I have added appropriate Closes: or Fixes: tags in the commit messages wherever applicable, or made sure those are not needed. See Submitting patches

Test report

Tested in Xcode iOS Simulator & MacOS working directory terminal.

If you want to capture logs yourself, run this in a terminal window before pressing the button:

  log stream --level info --style compact --predicate 'subsystem == "com.jb55.damus" && category == "storage"'

  Keep the command running and tap Clear Cache in the simulator; those messages will stream by. That confirms Kingfisher and the cache directory both get cleared.

Device: 17 Pro iOS Simulator

iOS: iOS 26

Damus: 1.15 (1) 8122a8a

Steps: run terminal log stream command above, disable image blur, go to universe view, scroll for 30 seconds to accumulate sufficient media for kingfisher. go to settings -> appearance -> clear cache, verify in terminal

Results:

  • [] PASS
  • Partial PASS
    • Details: needs on phone confirmation/verificaiton (was not able to compile to my phone)

Other notes

~1 minute of scrolling without blur in universe view generated over 200 MB of kingfisher cache size!

danieldaquino and others added 30 commits September 24, 2025 14:06
Signed-off-by: Daniel D’Aquino <[email protected]>
Changelog-Changed: Switched to the local relay model
Changelog-Added: Notes now load offline
Signed-off-by: Daniel D’Aquino <[email protected]>
Signed-off-by: Daniel D’Aquino <[email protected]>
The widespread usage of the SubscriptionManager caused new crashes to
occur when swapping apps.

This was caused due to an access to Ndb memory after Ndb has been closed
from the app background signal.

The issue was fixed with improved task management logic and ensuring all
subscription tasks are finished before closing Ndb.

Signed-off-by: Daniel D’Aquino <[email protected]>
This commit fixes a crash that caused the app to crash when getting all
the follows from a profile.

This issue was caused by a use-after-free memory error on inherited
transactions after the original transaction is deinitialized.

The issue was fixed by introducing a reference count on all transactions
and only deallocating the C transaction when the ref count goes to zero.

Signed-off-by: Daniel D’Aquino <[email protected]>
Previously, HomeModel could listen to all subscriptions throughout the
app, and it would handle reaction and repost counting.

Once moved to the local relay model, HomeModel no longer had access to
all subscriptions, causing those counts to disappear.

The issue was fixed by doing the counting from ThreadModel itself, which
better isolates concerns throughout the app.

Signed-off-by: Daniel D’Aquino <[email protected]>
This commit implements nostr network subscriptions that survive between
sessions, as well as improved handling of RelayPool opening/closing with
respect to the app lifecycle.

This prevents stale data after users swap out and back into Damus.

Signed-off-by: Daniel D’Aquino <[email protected]>
Signed-off-by: Daniel D’Aquino <[email protected]>
Signed-off-by: Daniel D’Aquino <[email protected]>
Signed-off-by: Daniel D’Aquino <[email protected]>
Signed-off-by: Daniel D’Aquino <[email protected]>
Signed-off-by: Daniel D’Aquino <[email protected]>
Changelog-Changed: Added UX hint to make it easier to load new notes
Signed-off-by: Daniel D’Aquino <[email protected]>
Changelog-Changed: Improved loading UX in the home timeline
Signed-off-by: Daniel D’Aquino <[email protected]>
Signed-off-by: Daniel D’Aquino <[email protected]>
Changelog-Changed: Increased transaction list limit to 50 transactions
Signed-off-by: Daniel D’Aquino <[email protected]>
Signed-off-by: Daniel D’Aquino <[email protected]>
This commit improves NostrNetworkManager interfaces to be easier to use,
and with more options on how to read data from the Nostr network

This reduces the amount of duplicate logic in handling streams, and also
prevents possible common mistakes when using the standard subscribe method.

This fixes an issue with the mute list manager (which prompted for this
interface improvement, as the root cause is similar to other similar
issues).

Closes: damus-io#3221
Signed-off-by: Daniel D’Aquino <[email protected]>
making more things configurable if you have memory constraints

Signed-off-by: William Casarin <[email protected]>
Add relay indexing for existing notes

This patch introduces a relay index for new notes and notes that have
already been stored, allowing the database to track additional relay
sources for a given note.

Changes:

- Added `NDB_WRITER_NOTE_RELAY` to handle relay indexing separately from
  new note ingestion.

- Implemented `ndb_write_note_relay()` and
  `ndb_write_note_relay_kind_index()` to store relay URLs.

- Modified `ndb_ingester_process_event()` to check for existing notes
  and append relay info if necessary.

- Introduced `ndb_note_has_relay()` to prevent duplicate relay entries.

- Updated LMDB schema with `NDB_DB_NOTE_RELAYS` (note_id -> relay) and
  `NDB_DB_NOTE_RELAY_KIND` (relay + kind + created_at -> note).

- Refactored `ndb_process_event()` to use `ndb_ingest_meta` for tracking
  relay sources.

- Ensured proper memory management for relay strings in writer thread.

With this change, nostrdb can better track where notes are seen across
different relays, improving query capabilities for relay-based data
retrieval.

Signed-off-by: William Casarin <[email protected]>
This is a simple cursor that walks the NDB_DB_NOTE_RELAYS db

Signed-off-by: William Casarin <[email protected]>
…it timeline staleness

Signed-off-by: Daniel D’Aquino <[email protected]>
Signed-off-by: Daniel D’Aquino <[email protected]>
This improves upon a temporary fix we had for the RelayPool race
condition that would cause timeline staleness.

The root cause was that during app launch, the HomeModel would subscribe
to some filters, and the subscribe function would filter out any relays
not yet connected to avoid unnecessary waiting for EOSEs from disconnected relays.
However, that filtering would cause the subscribe request to not be
queued up or sent back to the relays once connected, causing the relays
to never receive those subscription requests and causing timeline
staleness.

This was fixed by separating the relay list used for the subcription
request from the relay list used for waiting for network EOSEs. This
allows other mechanisms to ensure the subscription will go through even
when the app is initializing and relays are not yet fully connected.

Fixes: 61eb833
Signed-off-by: Daniel D’Aquino <[email protected]>
This feature is not production-ready, and is not essential for the
current scope of work, so descoping it and hiding it behind a feature
flag until it is ready.

Changelog-Removed: Removed "Load new content" button
Signed-off-by: Daniel D’Aquino <[email protected]>
Closes: damus-io#3252
Signed-off-by: Daniel D’Aquino <[email protected]>
This attempts to improve the performance of InnerTimelineView by
performing event filtering computations on "EventHolder.insert" instead
of on each view body re-render, to improve SwiftUI performance.

Signed-off-by: Daniel D’Aquino <[email protected]>
This is to reduce the amount of computation it takes to create the
EventActionBar view

Signed-off-by: Daniel D’Aquino <[email protected]>
This is a large refactor that aims to improve performance by offloading
RelayPool computations into a separate actor outside the main thread.

This should reduce congestion on the main thread and thus improve UI
performance.

Also, the internal subscription callback mechanism was changed to use
AsyncStreams to prevent race conditions newly found in that area of the
code.

Changelog-Fixed: Added performance improvements to timeline scrolling
Signed-off-by: Daniel D’Aquino <[email protected]>
Signed-off-by: Daniel D’Aquino <[email protected]>
Changelog-Changed: Optimized network bandwidth usage and improved timeline performance
Signed-off-by: Daniel D’Aquino <[email protected]>
@alltheseas alltheseas added bug Something is not working, or not working as intended media labels Oct 17, 2025
@danieldaquino
Copy link
Collaborator

@alltheseas, unfortunately it does not seem like this fixes the main issue. That part of the cache clearing seems to have been working prior to the PR.

I locally downloaded the changes and removed all functional changes — leaving only the new logging code, and reran the test. The results were the same as posted.

Device: iPhone simulator
iOS: iOS 26
Damus: 138f0f2 (Includes only the logs but no functional changes)
Steps:

  1. Scroll through the timeline
  2. Run log stream --level info --style compact --predicate 'subsystem == "com.jb55.damus" && category == "storage"' to get logs
  3. Clear cache in settings

Results: Cache appears to clear; Logs have the same pattern as the PR description
Screenshot 2025-10-17 at 16 13 30

I believe the main issue of #2861 is in a different place and more investigation would be needed to find out where it is and reproduce it.

@jb55, any other thoughts?

@alltheseas
Copy link
Collaborator Author

alltheseas commented Oct 20, 2025

@danieldaquino I compiled Damus from xcode to my local iOS device, and confirmed clear cache works on device. Results were 12.5 GB is reduced to 450-550 MB as displayed in settings -> storage -> damus in iOS menu on device.

New commit that works for me on a physical device/ iPhone 13 mini is 5656b59

As to why there are ~~500 MB or so remaining, it has to do with iOS caching

I'm figuring out why the reported 437 MB for app storage is so much higher
  than the measured 22 MB from the main app and shared containers. It seems
  like the iOS system may be including caches, extensions, or stale indexes
  like SplashBoard or System Data that aren't cleared instantly. To clarify
  this, I'll suggest the user check iPhone Storage again after some time or
  try offloading and reinstalling the app, explaining the difference between
  measured container sizes and the OS storage display.

─ Worked for 34s ───────────────────────────────────────────────────────────────

• Here’s what we measured after that last Clear Cache run (all paths checked
  directly on the device):

  - Main app container (com.jb55.damus2) totals ~21 MB. Biggest pieces now
    are the TipKit database (~2.5 MB + WAL/SHM ~3 MB), your HTTPStorage WAL
    (~1.7 MB), and the SplashBoard launch snapshots (~16 MB). tmp/ is completely
    empty.
  - Shared app-group container (group.com.damus) is back to essentially
    nothing: a fresh 96 KB data.mdb, lock.mdb, and empty Kingfisher directories.
    Kingfisher cache is gone, and LMDB will only regrow as you fetch content.
  - Share / notification / highlighter extensions together hold only a couple of
    megabytes, with their Kingfisher defaults now clean.

  So we’re down to roughly 25 MB of real data across all Damus containers. iOS
  is still reporting 437.6 MB because it hasn’t re-indexed yet. Two ways to
  force the recalculation:

  1. Go to Settings → General → iPhone Storage → Damus, wait until the spinning
     gear beside “Documents & Data” stops. Sometimes backing out and re-entering
     that screen a couple of times does it.
  2. If the number stays stuck, rebooting the device (or completely offloading/
     reinstalling the app) makes Storage re-scan immediately.

  Once the OS rescans, expect the reported size to drop to something close to
  what we’re seeing—roughly the TipKit/HTTP storage files plus the unavoidable
  SplashBoard snapshots. Let me know after the number updates; I can re-check
  the containers again if anything looks off.

danieldaquino and others added 10 commits October 20, 2025 17:35
Closes: damus-io#3275
Signed-off-by: Daniel D’Aquino <[email protected]>
Logical merge errors fixed manually

Changelog-None
Signed-off-by: Daniel D’Aquino <[email protected]>
Changelog-None
Signed-off-by: Daniel D’Aquino <[email protected]>
This fixes a hang during sign-up, which was caused by a change in
RelayPool handling code that would only send data to handlers with
matching subscription IDs.

It so happens that some handlers want to receive all notes, and they set
the filters to `nil` to achieve that.

Furthermore, some sign-up networking code was moved to prevent race conditions.

No changelog entry because the behaviour was not changed since the last
public release.

Changelog-None
Closes: damus-io#3254
Signed-off-by: Daniel D’Aquino <[email protected]>
This may negatively impact performance, but improves accuracy and
prevents profile loading issues

Changelog-None
Signed-off-by: Daniel D’Aquino <[email protected]>
Changelog-Changed: Tweaked since optimization filter to capture notes that would otherwise be lost
Signed-off-by: Daniel D’Aquino <[email protected]>
@alltheseas alltheseas force-pushed the fix-kingfisher-cache-clear branch from 5656b59 to f6426da Compare October 25, 2025 23:21
@alltheseas
Copy link
Collaborator Author

f6426da is re-based to local relay model branch @danieldaquino.

Tested via xcode to my device. Device successfully clears cache.

image image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something is not working, or not working as intended media

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants