Skip to main content

internal/infra/pg/exportstore.go

internal/infra/pg · 240 lines · 8 declarations · source

Declarations

type Exporter

type Exporter struct {
pool *pgxpool.Pool
schema Schema
}

Exporter answers "what do you hold about me".

Why it walks the same registry erasure does

Erasure discovers what to delete from `projection_kind` rather than from a list in code, so a projection added by a migration is swept without anybody remembering to add it. Export has exactly the same obligation and the opposite failure mode: a projection missing from a deletion leaves data behind, which a residual count catches — a projection missing from an export leaves data out, and nothing catches that at all. An export nobody compares against anything looks complete.

So it reads the same table. A kind that erasure would delete is a kind export must produce, and there is a test that fails when the two disagree.

Why it includes what was refused

`rejected_claim` holds verbatim quotes from a person's messages — claims the vocabulary would not admit or whose quote could not be located. They were not stored as facts and they are unambiguously that person's words. An export that omitted them would understate what is held, which is the one direction an export must not err in.

source

func NewExporter

func NewExporter(pool *pgxpool.Pool, schema Schema) *Exporter

source

var MaxExportRows

var MaxExportRows = 50000

Export gathers everything held about one data subject in one project.

Read in a single transaction at one snapshot. An export assembled across several reads could show a fact whose evidence had been erased between them — internally inconsistent, and the inconsistency would look like a defect in the memory rather than in the export. MaxExportRows bounds one export. A subject with more than this is exported by source instead, a document or a conversation at a time.

A variable rather than a constant so a test can lower it and watch the refusal happen; it is a bound this deployment holds, not a setting an operator turns up. Changing it at runtime would mean two exports of the same person disagreeing about what "too large" means.

The number is a ceiling on rows across every section, not bytes: a row's size is the person's own words and cannot be predicted here, while a row count is what both the export and the erasure receipt already report, so a caller who hits this can see why in the numbers they already have.

source

var ErrExportTooLarge

var ErrExportTooLarge = errors.New("the export exceeds the supported size; take it by source")

ErrExportTooLarge is a subject whose export exceeds MaxExportRows. It carries no content, only the bound, because the caller's next move is to narrow the request rather than to read a number.

source

method Exporter.Export

func (e *Exporter) Export(ctx context.Context, schema Schema, scope, dataSubjectID string) (domain.Export, error)

source

method Exporter.ExportSources

func (e *Exporter) ExportSources(ctx context.Context, schema Schema, scope string, sources []string) (domain.Export, error)

ExportSources answers what is held about a named set of turns, the way erasure by source deletes one. A document observed project-wide has no person, so a subject is not a way to reach it and, until now, neither was an export.

source

method Exporter.export

func (e *Exporter) export(ctx context.Context, schema Schema, scope string, sel sourceSelection) (domain.Export, error)

source

func exportRows

func exportRows(ctx context.Context, tx pgx.Tx, schema Schema, sql string, args ...any) ([]json.RawMessage, error)

source