package storage import ( "context" "sync" "time" slurpContext "chorus/pkg/slurp/context" "chorus/pkg/ucxl" ) // inMemoryContextStore offers a lightweight ContextStore implementation suitable for // local development and SEC-SLURP bootstrap scenarios. It keeps all context nodes in // process memory, providing the minimal surface required by the temporal subsystem until // the production storage stack is wired in. type inMemoryContextStore struct { mu sync.RWMutex contexts map[string]*slurpContext.ContextNode } // NewInMemoryContextStore constructs an in-memory ContextStore. func NewInMemoryContextStore() ContextStore { return &inMemoryContextStore{ contexts: make(map[string]*slurpContext.ContextNode), } } func (s *inMemoryContextStore) StoreContext(ctx context.Context, node *slurpContext.ContextNode, roles []string) error { if node == nil { return nil } s.mu.Lock() defer s.mu.Unlock() s.contexts[node.UCXLAddress.String()] = node return nil } func (s *inMemoryContextStore) RetrieveContext(ctx context.Context, address ucxl.Address, role string) (*slurpContext.ContextNode, error) { s.mu.RLock() defer s.mu.RUnlock() node, ok := s.contexts[address.String()] if !ok { return nil, ErrNotFound } return node, nil } func (s *inMemoryContextStore) UpdateContext(ctx context.Context, node *slurpContext.ContextNode, roles []string) error { if node == nil { return nil } s.mu.Lock() defer s.mu.Unlock() s.contexts[node.UCXLAddress.String()] = node return nil } func (s *inMemoryContextStore) DeleteContext(ctx context.Context, address ucxl.Address) error { s.mu.Lock() defer s.mu.Unlock() delete(s.contexts, address.String()) return nil } func (s *inMemoryContextStore) ExistsContext(ctx context.Context, address ucxl.Address) (bool, error) { s.mu.RLock() defer s.mu.RUnlock() _, ok := s.contexts[address.String()] return ok, nil } func (s *inMemoryContextStore) ListContexts(ctx context.Context, criteria *ListCriteria) ([]*slurpContext.ContextNode, error) { s.mu.RLock() defer s.mu.RUnlock() results := make([]*slurpContext.ContextNode, 0, len(s.contexts)) for _, node := range s.contexts { results = append(results, node) } return results, nil } func (s *inMemoryContextStore) SearchContexts(ctx context.Context, query *SearchQuery) (*SearchResults, error) { return &SearchResults{ Results: []*SearchResult{}, TotalResults: 0, ProcessingTime: 0, Facets: map[string]map[string]int{}, Suggestions: []string{}, ProcessedAt: time.Now(), }, nil } func (s *inMemoryContextStore) BatchStore(ctx context.Context, batch *BatchStoreRequest) (*BatchStoreResult, error) { if batch == nil { return &BatchStoreResult{}, nil } s.mu.Lock() defer s.mu.Unlock() success := 0 for _, item := range batch.Contexts { if item == nil || item.Context == nil { continue } s.contexts[item.Context.UCXLAddress.String()] = item.Context success++ } return &BatchStoreResult{SuccessCount: success}, nil } func (s *inMemoryContextStore) BatchRetrieve(ctx context.Context, batch *BatchRetrieveRequest) (*BatchRetrieveResult, error) { result := &BatchRetrieveResult{ Contexts: make(map[string]*slurpContext.ContextNode), Errors: make(map[string]error), ProcessedAt: time.Now(), ProcessingTime: 0, } if batch == nil { return result, nil } s.mu.RLock() defer s.mu.RUnlock() for _, address := range batch.Addresses { key := address.String() if node, ok := s.contexts[key]; ok { result.Contexts[key] = node result.SuccessCount++ } else { result.Errors[key] = ErrNotFound result.ErrorCount++ } } return result, nil } func (s *inMemoryContextStore) GetStorageStats(ctx context.Context) (*StorageStatistics, error) { s.mu.RLock() defer s.mu.RUnlock() return &StorageStatistics{ TotalContexts: int64(len(s.contexts)), LocalContexts: int64(len(s.contexts)), LastSyncTime: time.Now(), }, nil } func (s *inMemoryContextStore) Sync(ctx context.Context) error { return nil } func (s *inMemoryContextStore) Backup(ctx context.Context, destination string) error { return nil } func (s *inMemoryContextStore) Restore(ctx context.Context, source string) error { return nil }