Class InMemoryActivityStore
- All Implemented Interfaces:
ActivityStore
ActivityStore: a process-local, bounded, per-session ring-buffer that keeps
only the most recent slice of activity and forgets everything when the process stops.
What this class is for
This is the v1 storage decision made concrete. The Ambient Activity feature only ever reads a recent window of events to inject into a prompt, so it does not need durable storage — and keeping activity in memory is also the most privacy-friendly default, since it evaporates with the session rather than accumulating on disk. Each session gets its own fixed-capacity buffer; once full, the oldest event is evicted to make room for the newest, so memory use is bounded no matter how long a user works.
Familiar analogy: a whiteboard by someone's desk that only fits twenty lines. They jot what they're doing as they go; when the board fills up, the top line gets wiped to write a new one at the bottom. You can always read the last twenty things at a glance, but there is no filing cabinet — wipe the board (end the session) and the history is gone. That ephemerality is a feature here, not a limitation.
Why per-session buffers
Partitioning by session keeps one user's recent activity bounded independently of everyone
else's, and makes the common "recent in this session/tab" read cheap — we scan one small buffer,
not a global log. Combined with TabForge's @TabScoped model, this is what gives per-tab
working memory essentially for free.
Thread-safety
record(dyntabs.ai.activity.UserActivityEvent) runs on user request threads; query(dyntabs.ai.activity.ActivityQuery) may run on another thread when the
assistant is invoked. The per-session buffers live in a ConcurrentHashMap, and every read
or write of an individual buffer is guarded by synchronizing on that buffer. Snapshots are copied
out under the lock and filtered outside it, so a query never blocks recording for longer than a
quick array copy.
Registered as the Default ActivityStore with a low (library-default) priority,
so an application can override it simply by providing its own enabled alternative.
- See Also:
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intDefault number of events retained per session before the oldest is evicted. -
Constructor Summary
ConstructorsConstructorDescriptionCreate a store with thedefault per-session capacity.InMemoryActivityStore(int capacityPerSession) Create a store with an explicit per-session capacity (handy for tests). -
Method Summary
Modifier and TypeMethodDescriptionquery(ActivityQuery query) Return the events matching the given query, oldest first, capped by the query's limit.voidrecord(UserActivityEvent event) Append one event to the timeline.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface dyntabs.ai.activity.ActivityStore
recent
-
Field Details
-
DEFAULT_CAPACITY_PER_SESSION
public static final int DEFAULT_CAPACITY_PER_SESSIONDefault number of events retained per session before the oldest is evicted.- See Also:
-
-
Constructor Details
-
InMemoryActivityStore
public InMemoryActivityStore()Create a store with thedefault per-session capacity. -
InMemoryActivityStore
public InMemoryActivityStore(int capacityPerSession) Create a store with an explicit per-session capacity (handy for tests).- Parameters:
capacityPerSession- the maximum events retained per session; must be positive
-
-
Method Details
-
record
Description copied from interface:ActivityStoreAppend one event to the timeline.Implementations should treat this as best-effort and non-throwing: it runs on the user's request thread, and recording is never more important than the action being recorded.
- Specified by:
recordin interfaceActivityStore- Parameters:
event- the event to store; must not benull
-
query
Description copied from interface:ActivityStoreReturn the events matching the given query, oldest first, capped by the query's limit.- Specified by:
queryin interfaceActivityStore- Parameters:
query- the filter describing which slice to return; must not benull- Returns:
- a chronological, caller-owned snapshot list; never
null(empty if nothing matches)
-