156 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 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
 | |
| }
 | 
