Moved broadly useful helper functions upstream into feedkit

This commit is contained in:
2026-03-28 11:29:09 -05:00
parent 4910440756
commit 3ef93faf69
6 changed files with 591 additions and 0 deletions

27
sinks/helpers.go Normal file
View File

@@ -0,0 +1,27 @@
package sinks
import (
"fmt"
"strings"
"gitea.maximumdirect.net/ejr/feedkit/config"
)
// RegisterPostgresSchemaForConfiguredSinks registers one Postgres schema for each
// configured sink using driver=postgres.
func RegisterPostgresSchemaForConfiguredSinks(cfg *config.Config, schema PostgresSchema) error {
if cfg == nil {
return fmt.Errorf("register postgres schemas: config is nil")
}
for i, sk := range cfg.Sinks {
if !strings.EqualFold(strings.TrimSpace(sk.Driver), "postgres") {
continue
}
if err := RegisterPostgresSchema(sk.Name, schema); err != nil {
return fmt.Errorf("register postgres schema for sinks[%d] name=%q: %w", i, sk.Name, err)
}
}
return nil
}

86
sinks/helpers_test.go Normal file
View File

@@ -0,0 +1,86 @@
package sinks
import (
"context"
"fmt"
"strings"
"testing"
"time"
"gitea.maximumdirect.net/ejr/feedkit/config"
"gitea.maximumdirect.net/ejr/feedkit/event"
)
func TestRegisterPostgresSchemaForConfiguredSinksNilConfig(t *testing.T) {
err := RegisterPostgresSchemaForConfiguredSinks(nil, testPostgresSchema())
if err == nil {
t.Fatalf("RegisterPostgresSchemaForConfiguredSinks(nil) expected error")
}
if !strings.Contains(err.Error(), "config is nil") {
t.Fatalf("error = %q, want config is nil", err)
}
}
func TestRegisterPostgresSchemaForConfiguredSinksNonPostgresNoOp(t *testing.T) {
cfg := &config.Config{
Sinks: []config.SinkConfig{
{Name: uniqueSinkName("stdout"), Driver: "stdout"},
{Name: uniqueSinkName("nats"), Driver: "nats"},
},
}
if err := RegisterPostgresSchemaForConfiguredSinks(cfg, testPostgresSchema()); err != nil {
t.Fatalf("RegisterPostgresSchemaForConfiguredSinks(non-postgres) error = %v", err)
}
}
func TestRegisterPostgresSchemaForConfiguredSinksDuplicateRegistrationFails(t *testing.T) {
cfg := &config.Config{
Sinks: []config.SinkConfig{
{Name: uniqueSinkName("pg"), Driver: "postgres"},
},
}
if err := RegisterPostgresSchemaForConfiguredSinks(cfg, testPostgresSchema()); err != nil {
t.Fatalf("first RegisterPostgresSchemaForConfiguredSinks() error = %v", err)
}
err := RegisterPostgresSchemaForConfiguredSinks(cfg, testPostgresSchema())
if err == nil {
t.Fatalf("second RegisterPostgresSchemaForConfiguredSinks() expected duplicate error")
}
if !strings.Contains(err.Error(), "already registered") {
t.Fatalf("error = %q, want already registered", err)
}
}
func testPostgresSchema() PostgresSchema {
return PostgresSchema{
Tables: []PostgresTable{
{
Name: "events",
Columns: []PostgresColumn{
{Name: "event_id", Type: "TEXT", Nullable: false},
{Name: "emitted_at", Type: "TIMESTAMPTZ", Nullable: false},
},
PrimaryKey: []string{"event_id"},
PruneColumn: "emitted_at",
},
},
MapEvent: func(_ context.Context, e event.Event) ([]PostgresWrite, error) {
return []PostgresWrite{
{
Table: "events",
Values: map[string]any{
"event_id": e.ID,
"emitted_at": e.EmittedAt,
},
},
}, nil
},
}
}
func uniqueSinkName(prefix string) string {
return fmt.Sprintf("%s_%d", prefix, time.Now().UnixNano())
}