Skip to content

feat(sharing): opt-in lazy auto-refresh of stale shared copies on read#21

Closed
doctatortot wants to merge 1 commit into
ourmem:mainfrom
doctatortot:feat/auto-refresh-shares
Closed

feat(sharing): opt-in lazy auto-refresh of stale shared copies on read#21
doctatortot wants to merge 1 commit into
ourmem:mainfrom
doctatortot:feat/auto-refresh-shares

Conversation

@doctatortot
Copy link
Copy Markdown
Contributor

Problem

Shared copies are snapshots. When the source memory is updated, copies don't auto-update — users must detect staleness via ?check_stale=true and manually reshare. Shared copies silently drift from their source.

Approach

Opt-in lazy refresh on read. With OMEM_AUTO_REFRESH_SHARES=true, reading a shared copy whose source has a newer version transparently refreshes it (pulls current source content + vector) before returning, so a reader never sees a stale snapshot. Default off → zero behavior change.

The refresh primitive already lived inside reshare_memory (fetch source + vector → make_shared_copycreatesoft_delete old). This PR extracts it into a reusable refresh_shared_copy(store_manager, space_store, copy, tenant, agent) helper used by both the existing reshare endpoint and the new read path. The source vector is copied as-is, so no re-embedding — refresh is cheap. Wired into get_memory; source-deleted copies are left untouched.

Why only get_memory (not search / push / worker)

Search ranks on the copy's vector, so refreshing mid-search would mutate data on a read and still rank on the stale vector. Search-result freshness wants push-on-update or a background worker (which needs a source→copies reverse index) — deliberately left as a follow-up. Lazy-on-read is the minimal, correct piece: costs nothing when nothing is stale, and only refreshes copies that are actually read.

Config

OMEM_AUTO_REFRESH_SHARES (bool, default false).

Tests

  • test_refresh_shared_copy_helper: source → share → bump source → refresh → asserts fresh content, advanced source_version, no-longer-stale, old copy soft-deleted.
  • Full suite green (389 passed / 0 failed). reshare_memory behaviour unchanged (it now delegates to the shared helper; existing reshare/stale tests pass). fmt + clippy clean (no new warnings).

Refresh logs a Reshare sharing event for audit.

Shared copies are snapshots: when the source memory is updated, copies
don't auto-update, so readers can see stale content unless they poll
?check_stale=true and manually reshare.

Add OMEM_AUTO_REFRESH_SHARES (default false). When enabled, reading a
shared copy whose source has a newer version transparently refreshes it
(pulls current source content + vector) before returning.

Extract the refresh primitive out of reshare_memory into a reusable
refresh_shared_copy(store_manager, space_store, copy, tenant, agent)
helper, used by both the reshare endpoint and the new read path. The
source vector is copied as-is, so refresh does not re-embed.

Wired into get_memory; source-deleted copies are left untouched. Search
is intentionally not auto-refreshed (it ranks on the copy vector; that
wants push-on-update or a worker -- left as a follow-up).

Tests: test_refresh_shared_copy_helper; full suite green (389 passed).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@yhyyz
Copy link
Copy Markdown
Contributor

yhyyz commented May 21, 2026

Merge conflict after recent merges (likely sharing.rs). Could you rebase onto main? Will merge immediately after. 🙏

yhyyz added a commit that referenced this pull request May 21, 2026
- feat(sharing): opt-in per-user rate limiting (PR #24)
  Token-bucket limiter on all 8 sharing handlers.
  OMEM_SHARE_RATE_PER_MIN=0 (default, disabled).

- feat(sharing): opt-in lazy auto-refresh stale shares on read (PR #21)
  Extracts refresh_shared_copy() helper, reused by reshare endpoint
  and new auto-refresh-on-read path in get_memory.
  OMEM_AUTO_REFRESH_SHARES=false (default, disabled).

Co-authored-by: doctatortot <doctatortot@users.noreply.github.com>
@yhyyz
Copy link
Copy Markdown
Contributor

yhyyz commented May 21, 2026

Applied in 4db9c5e — resolved the conflict on our side (was caused by our merge order of #22/#23 before #21). The refresh_shared_copy extraction and auto-refresh on read are working perfectly. 394 tests pass. Thanks @doctatortot! 👍

@yhyyz yhyyz closed this May 21, 2026
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.

2 participants