package postgres import ( "context" "encoding/json" "fmt" "git.cin.su/m/Assistant/contracts/world" worlddomain "git.cin.su/m/Assistant/modules/world/domain" "github.com/jackc/pgx/v5/pgxpool" ) type WorldRepository struct{ pool *pgxpool.Pool } func OpenWorld(ctx context.Context, config ContinuityConfig) (*WorldRepository, error) { pool, err := openPool(ctx, config) if err != nil { return nil, err } return &WorldRepository{pool: pool}, nil } func (r *WorldRepository) Close() { r.pool.Close() } func (r *WorldRepository) SaveKindDefinition(ctx context.Context, value world.WorldObjectKindDefinition) error { if err := worlddomain.ValidateKindDefinition(value); err != nil { return err } var parentOwner, parentKind, parentID string var parentRevision *uint64 if value.ParentKindRef != nil { parentOwner, parentKind, parentID = value.ParentKindRef.OwnerNamespace, value.ParentKindRef.SemanticKind, string(value.ParentKindRef.StableID) if value.ParentKindRef.Revision != nil { revision := uint64(*value.ParentKindRef.Revision) parentRevision = &revision } } _, err := r.pool.Exec(ctx, `INSERT INTO world.kind_definitions(kind_definition_id,kind_key,revision,display_name,parent_owner_namespace,parent_semantic_kind,parent_stable_id,parent_revision,lifecycle,definition_digest,recorded_at_unix_millis) VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11) ON CONFLICT(kind_definition_id) DO NOTHING`, value.ID, value.KindKey, value.Revision, value.DisplayName, parentOwner, parentKind, parentID, parentRevision, value.Lifecycle, value.DefinitionDigest, value.RecordedAt) return err } func (r *WorldRepository) SaveObject(ctx context.Context, value world.WorldObject) error { if err := worlddomain.ValidateObject(value); err != nil { return err } _, err := r.pool.Exec(ctx, `INSERT INTO world.objects(world_object_id,principal_id,kind_owner_namespace,kind_semantic_kind,kind_stable_id,kind_revision,lifecycle,created_at_unix_millis) VALUES($1,$2,$3,$4,$5,$6,$7,$8) ON CONFLICT(world_object_id) DO NOTHING`, value.ID, value.PrincipalID, value.KindDefinitionRef.OwnerNamespace, value.KindDefinitionRef.SemanticKind, value.KindDefinitionRef.StableID, value.KindRevision, value.Lifecycle, value.CreatedAt) return err } func (r *WorldRepository) SaveAlias(ctx context.Context, value world.WorldAlias) error { if err := worlddomain.ValidateAlias(value); err != nil { return err } _, err := r.pool.Exec(ctx, `INSERT INTO world.aliases(world_alias_id,principal_id,world_object_id,alias,recorded_at_unix_millis) VALUES($1,$2,$3,$4,$5) ON CONFLICT(world_alias_id) DO NOTHING`, value.ID, value.PrincipalID, value.ObjectID, value.Alias, value.RecordedAt) return err } func (r *WorldRepository) SaveFacetDefinition(ctx context.Context, value world.FacetDefinition) error { if err := worlddomain.ValidateFacetDefinition(value); err != nil { return err } payload, err := json.Marshal(value.ValueType) if err != nil { return fmt.Errorf("encode facet value type: %w", err) } _, err = r.pool.Exec(ctx, `INSERT INTO world.facet_definitions(facet_definition_id,kind_key,revision,facet_key,value_type,definition_digest,recorded_at_unix_millis) VALUES($1,$2,$3,$4,$5,$6,$7) ON CONFLICT(facet_definition_id) DO NOTHING`, value.ID, value.KindKey, value.Revision, value.FacetKey, payload, value.DefinitionDigest, value.RecordedAt) return err } func (r *WorldRepository) SaveRelationDefinition(ctx context.Context, value world.RelationDefinition) error { if err := worlddomain.ValidateRelationDefinition(value); err != nil { return err } _, err := r.pool.Exec(ctx, `INSERT INTO world.relation_definitions(relation_definition_id,kind_key,revision,relation_key,target_kind_key,definition_digest,recorded_at_unix_millis) VALUES($1,$2,$3,$4,$5,$6,$7) ON CONFLICT(relation_definition_id) DO NOTHING`, value.ID, value.KindKey, value.Revision, value.RelationKey, value.TargetKindKey, value.DefinitionDigest, value.RecordedAt) return err } func (r *WorldRepository) SaveResolution(ctx context.Context, value world.IdentityResolutionDecisionRecord) error { if err := worlddomain.ValidateResolution(value); err != nil { return err } candidates, err := json.Marshal(value.Candidates) if err != nil { return fmt.Errorf("encode resolution candidates: %w", err) } evidence, err := json.Marshal(value.Evidence) if err != nil { return fmt.Errorf("encode resolution evidence: %w", err) } _, err = r.pool.Exec(ctx, `INSERT INTO world.identity_resolution_decisions(resolution_decision_id,principal_id,candidates,decision,evidence,confidence_millis,decided_at_unix_millis,revision) VALUES($1,$2,$3,$4,$5,$6,$7,$8) ON CONFLICT(resolution_decision_id) DO NOTHING`, value.ID, value.PrincipalID, candidates, value.Decision, evidence, value.ConfidenceMillis, value.DecidedAt, value.Revision) return err } func (r *WorldRepository) SaveLineage(ctx context.Context, value world.WorldLineage) error { if err := worlddomain.ValidateLineage(value); err != nil { return err } sources, err := json.Marshal(value.SourceRefs) if err != nil { return fmt.Errorf("encode lineage sources: %w", err) } successors, err := json.Marshal(value.SuccessorRefs) if err != nil { return fmt.Errorf("encode lineage successors: %w", err) } _, err = r.pool.Exec(ctx, `INSERT INTO world.lineage(lineage_id,operation,source_refs,successor_refs,recorded_at_unix_millis) VALUES($1,$2,$3,$4,$5) ON CONFLICT(lineage_id) DO NOTHING`, value.ID, value.Operation, sources, successors, value.RecordedAt) return err }