feat: bootstrap temporal graph via dht-backed init
This commit is contained in:
155
pkg/slurp/storage/context_store_inmemory.go
Normal file
155
pkg/slurp/storage/context_store_inmemory.go
Normal file
@@ -0,0 +1,155 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user