Files
story/internal/callmemory/story_extraction.go
T

56 lines
2.1 KiB
Go
Raw Normal View History

package callmemory
import (
"context"
"encoding/json"
"fmt"
"data-terminal-cloud/internal/outbox"
"github.com/jackc/pgx/v5"
)
// Story review is independent of automatic Viking memory extraction. Schedule
// only drained, authorized calls; late subtitles get a new revision and event.
func (s *Service) enqueueDirectStories(ctx context.Context, tx pgx.Tx) error {
rows, err := tx.Query(ctx, `SELECT c.id::text,c.tenant_id::text,c.transcript_revision,c.privacy_epoch
FROM call_session c WHERE c.ended_at IS NOT NULL AND c.transcript_state IN ('COMPLETE','PARTIAL')
AND c.transcript_revision>0 AND c.budget_snapshot->>'protocol'='DIRECT-CHAT-1'
AND c.budget_snapshot->>'story_extraction_allowed'='true' AND call_story_authorized(c.id)
AND NOT EXISTS(SELECT 1 FROM call_story_extraction e WHERE e.session_id=c.id AND e.transcript_revision=c.transcript_revision AND e.privacy_epoch=c.privacy_epoch)
AND NOT EXISTS(SELECT 1 FROM outbox_event o WHERE o.aggregate_id=c.id AND o.event_type='call.story_extraction_requested'
AND o.deduplication_key='call-story-v1:'||c.id::text||':'||c.transcript_revision::text||':'||c.privacy_epoch::text)
ORDER BY c.ended_at,c.id LIMIT 20`)
if err != nil {
return err
}
type pending struct {
session, tenant string
revision, epoch int64
}
items := []pending{}
for rows.Next() {
var item pending
if err = rows.Scan(&item.session, &item.tenant, &item.revision, &item.epoch); err != nil {
rows.Close()
return err
}
items = append(items, item)
}
err = rows.Err()
rows.Close()
if err != nil {
return err
}
for _, item := range items {
key := fmt.Sprintf("call-story-v1:%s:%d:%d", item.session, item.revision, item.epoch)
payload, _ := json.Marshal(map[string]int64{"generation_version": item.revision, "privacy_epoch": item.epoch})
if _, err = outbox.NewStore(s.pool).Enqueue(ctx, tx, outbox.NewEvent{
TenantID: &item.tenant, AggregateType: "call_session", AggregateID: item.session,
EventType: "call.story_extraction_requested", DeduplicationKey: &key, Payload: payload,
}); err != nil {
return err
}
}
return nil
}