inmemory.go
Overview
The inmemory.go file implements an in-memory artifact storage service that conforms to the artifact.Service interface defined in the Artifact Management module. This service provides a transient, thread-safe, and versioned artifact store primarily intended for testing, demonstration, and local development scenarios.
Artifacts are stored entirely in memory using an ordered map keyed by a composite artifactKey encoding the application name, user ID, session ID, filename, and version. The service supports storing multiple versions of artifacts, retrieving the latest or a specific version, listing all artifact filenames, and deleting artifacts by version or entirely.
The implementation manages concurrent access via a read-write mutex and distinguishes between session-scoped and user-scoped artifacts by namespace conventions. This enables artifacts to be shared across sessions for a given user when the filename has a user: prefix.
The service interacts closely with the genai.Part type representing artifact content and fits into the larger system as a backend for artifact persistence, complementing other backends like Google Cloud Storage.
Types and Data Structures
inMemoryService
Description:
Concrete struct implementing theartifact.Serviceinterface using in-memory storage.Fields:
mu sync.RWMutex— Protects concurrent access to theartifactsmap.artifacts omap.Map[string, *genai.Part]— Ordered map storing artifacts by encoded keys.
Usage:
Created via theInMemoryService()constructor function, it serves as a lightweight, ephemeral backend for storing artifacts.
artifactKey
Description:
Composite key struct that uniquely identifies an artifact version using multiple fields.Fields:
AppName string— Application scope.UserID string— User identifier.SessionID string— Session context or"user"for user-scoped artifacts.FileName string— Artifact filename (supports user namespace via prefix).Version int64— Artifact version number; stored in reverse order for sorting.
Methods:
Encode() string— Encodes the key into an ordered string suitable for map storage and range scans.Decode(key string) error— Decodes an encoded string back into anartifactKey.
Usage:
Used internally as the key in the ordered map to enable efficient iteration and version management.
Functions and Methods
Constructor
func InMemoryService() Service
Description: Returns a new instance of the in-memory artifact service implementing
artifact.Service.Parameters: None.
Returns:
Serviceinterface implemented by*inMemoryService.Example:
svc := artifact.InMemoryService()
Namespace Utility
func fileHasUserNamespace(filename string) bool
Description: Checks if a filename indicates a user-scoped artifact by testing if it starts with
"user:".Parameters:
filename— Name of the artifact file.
Returns:
trueif filename is user-scoped; otherwisefalse.
artifactKey Methods
func (ak artifactKey) Encode() string
Encodes the artifact key fields into a single string using the
orderedpackage.The version is reversed (
ordered.Rev) to ensure descending version order during scans.
func (ak *artifactKey) Decode(key string) error
Decodes an encoded string back into the
artifactKeyfields.Properly reverses the version from the stored reversed form.
Returns an error if decoding fails.
Internal Iteration Helpers
func (s *inMemoryService) scan(lo, hi string) iter.Seq2[artifactKey, *genai.Part]
Returns an iterator function over all key-value pairs within the range
lo ≤ key ≤ hi.Decodes each key from the map and yields the
artifactKeyand associatedgenai.Part.Stops iteration if the
yieldcallback returns false.
Internal Getters and Setters
func (s *inMemoryService) find(appName, userID, sessionID, fileName string) (int64, *genai.Part, bool)
Finds the latest version of an artifact matching the specified key fields.
Performs a descending version scan by encoding a range from max to min version.
Returns the highest version number, the artifact part, and a boolean indicating if found.
func (s *inMemoryService) get(appName, userID, sessionID, fileName string, version int64) (*genai.Part, bool)
Retrieves a specific artifact version by constructing the exact encoded key.
Returns the artifact part and a boolean indicating if found.
func (s *inMemoryService) set(appName, userID, sessionID, fileName string, version int64, artifact *genai.Part)
Stores or updates an artifact at the specified key and version.
func (s *inMemoryService) delete(appName, userID, sessionID, fileName string, version int64)
Removes an artifact identified by the full key and version.
Interface Methods (artifact.Service)
Save
func (s *inMemoryService) Save(ctx context.Context, req *SaveRequest) (*SaveResponse, error)
Description: Saves an artifact, automatically incrementing the version.
Parameters:
ctx— context for cancellation and deadlines.req—SaveRequestcontaining artifact metadata and content.
Returns:
SaveResponsecontaining the assigned version.errorif validation fails or other errors occur.
Details:
Validates request fields.
Detects user-scoped artifacts by filename prefix and sets session ID to
"user".Locks for writing.
Finds the latest version and increments it by 1.
Stores the artifact in the map with the new version.
Unlocks and returns the new version.
Example Usage:
resp, err := svc.Save(ctx, &artifact.SaveRequest{
AppName: "myapp",
UserID: "user123",
SessionID: "sess456",
FileName: "file.txt",
Part: partData,
})
if err != nil {
// handle error
}
fmt.Println("Saved version:", resp.Version)
Delete
func (s *inMemoryService) Delete(ctx context.Context, req *DeleteRequest) error
Description: Deletes an artifact version or all versions if no version specified.
Parameters:
ctx— context object.req—DeleteRequestspecifying artifact metadata and version.
Returns:
errorif validation fails.Details:
Validates the request.
Adjusts session ID for user-scoped files.
If
Version != 0, deletes the specific version.Otherwise, deletes all versions by scanning the range and deleting keys.
Behavior: Deleting a non-existent artifact version is not an error.
Load
func (s *inMemoryService) Load(ctx context.Context, req *LoadRequest) (*LoadResponse, error)
Description: Loads an artifact by key and optional version. Defaults to latest version if none specified.
Parameters:
ctx— context object.req—LoadRequestwith artifact metadata and optional version.
Returns:
LoadResponsecontaining the artifact part.errorif artifact not found or validation fails.
Details:
Validates request.
Adjusts session ID for user-scoped artifacts.
If version specified and > 0, loads exactly that version.
Otherwise, finds the latest version.
Locks for reading during access.
List
func (s *inMemoryService) List(ctx context.Context, req *ListRequest) (*ListResponse, error)
Description: Lists all artifact filenames available within the session namespace, including user-scoped artifacts.
Parameters:
ctx— context object.req—ListRequestcontaining app, user, and session info.
Returns:
ListResponsewith sorted list of filenames.errorif validation fails.
Details:
Validates request.
Performs two scans:
Session-scoped artifacts.
User-scoped artifacts under the
"user"namespace.
Merges filenames into a map to deduplicate.
Converts keys to a sorted slice.
Versions
func (s *inMemoryService) Versions(ctx context.Context, req *VersionsRequest) (*VersionsResponse, error)
Description: Lists all versions available for a given artifact.
Parameters:
ctx— context object.req—VersionsRequestwith artifact metadata.
Returns:
VersionsResponsecontaining a slice of versions.errorif no versions found or validation fails.
Details:
Validates request.
Adjusts session ID for user-scoped files.
Scans all versions in descending order.
Collects versions into a slice.
Returns error if none found.
Important Implementation Details
Key Encoding and Ordering:
The use ofordered.Encodewith version reversed (ordered.Rev) allows efficient descending scans by version. This means the latest versions are found first in iteration.User Namespace Handling:
Files prefixed with"user:"are stored under a special session ID"user", making them accessible to all sessions for the user. This is consistently applied in save, load, delete, list, and versions methods.Concurrency Control:
Read-write mutexmuguards access to theartifactsmap to allow concurrent reads and exclusive writes.Range Scans:
Thescanmethod enables iteration over a range of keys, facilitating version enumeration, listing, and deletion of multiple versions.Error Handling:
Methods validate incoming requests and return wrapped errors with context. Missing artifacts result infs.ErrNotExistwrapped errors.
Interactions with Other System Parts
Implements the
artifact.Serviceinterface used system-wide for artifact persistence (Artifact Management).Relies on the
genai.Parttype to represent artifact content, which supports both binary data and textual parts.Used primarily in testing and development environments where a persistent storage backend is unnecessary.
Can be substituted transparently with other backends such as the Google Cloud Storage Service without changing higher-level logic.
Agents and tools that use artifacts interact with this service indirectly via adapters or directly when configured for in-memory storage.
Integrates with session management (Session Management) by using session IDs and user IDs to scope artifacts.
Visual Diagram
classDiagram
class inMemoryService {
+Save()
+Load()
+Delete()
+List()
+Versions()
-mu : sync.RWMutex
-artifacts : omap.Map
}
class artifactKey {
-AppName : string
-UserID : string
-SessionID : string
-FileName : string
-Version : int64
+Encode()
+Decode()
}
inMemoryService "1" --> "*" artifactKey : stores by
inMemoryService ..> sync.RWMutex : concurrency control
inMemoryService ..> omap.Map : internal storage
This diagram depicts the core class inMemoryService with its main methods and internal fields. It shows the relationship to the artifactKey struct, which uniquely identifies stored artifacts by composite keys. The service uses a read-write mutex and an ordered map internally to manage concurrent, versioned artifact storage.
References
See the Artifact Management topic for detailed interface definitions and system-wide artifact handling concepts.
The
artifactKeyencoding scheme aligns with the artifact key encoding described in Artifact Management.The
genai.Parttype used for artifact content is defined elsewhere in the project and provides flexible content representation.Concurrency and ordered map usage patterns reflect common design for efficient in-memory storage with versioned keys.