Files
summercms/modules/pier/store.go
Jakub Zych cfdbaf0e47 feat(19.7-02): pier MCP module tracer with in-process dispatch and sessions
- modules/pier: Host contract, mcp.* config, catalog compiled from
  pact.HasMCP (prefixing, route binding, guard resolution, schema
  reflection, annotations), per-request identity through the published
  verifier and resolvers, built-in backend guard provider, in-process
  dispatch with the bouncer marker, per-identity SDK server with the
  per-request re-filter, stateful session router with rehydration over a
  memory store, audit lines
- modules/surf/pier_on.go: the summercms_mcp hook adapting the router to
  pier.Host; the untagged hello binary carries no SDK
- go.mod: go-sdk v1.8.0 and jsonschema-go v0.4.3 (decision note committed
  before this change)
- TestPierTracerSmoke: SDK client lists and calls acme_echo end to end
  through surf's compiled guard chain; README and root table row
2026-10-22 18:15:59 +02:00

47 lines
1.7 KiB
Go

package pier
import (
"context"
"encoding/json"
"time"
)
// Record is one stored session: the binding key of the identity that opened
// it, the JSON of the SDK's ServerSessionState once initialised (nil until
// then) and the creation time.
type Record struct {
Binding string `json:"binding"`
State json.RawMessage `json:"state,omitempty"`
Created time.Time `json:"created"`
}
// Event is what instances publish to each other: a session ended by DELETE
// (EventEnded, with SessionID) or a subject change (the pact
// MCPSubjectChanged kinds, with Guard and UserID). Instance names the
// publisher so it can skip its own echo when it has already acted.
type Event struct {
Kind string `json:"kind"`
Guard string `json:"guard,omitempty"`
UserID uint `json:"user_id,omitempty"`
SessionID string `json:"session_id,omitempty"`
Instance string `json:"instance,omitempty"`
}
// EventEnded is the kind of a session-ended event.
const EventEnded = "ended"
// Store is the session registry and the event channel shared by every
// instance of the application: memory for one instance (and tests), Redis
// for several. Put writes a record with a TTL, Touch slides it, Count
// answers the live sessions of one binding, Publish and Subscribe carry
// Events.
type Store interface {
Put(ctx context.Context, id string, rec Record, ttl time.Duration) error
Get(ctx context.Context, id string) (Record, bool, error)
Touch(ctx context.Context, id string, ttl time.Duration) error
Delete(ctx context.Context, id string) error
Count(ctx context.Context, binding string) (int, error)
Publish(ctx context.Context, ev Event) error
Subscribe(ctx context.Context, fn func(Event)) error
}