From 0a657682f6aaaeba7d2fab79608adeeb405098cb Mon Sep 17 00:00:00 2001 From: Natercio Moniz Date: Sat, 11 Jul 2026 16:28:35 +0100 Subject: [PATCH] use options in the report --- cmd/any2anexoj-cli/main.go | 2 +- internal/report.go | 37 ++++++++++++++++++++++++++++++------- internal/report_test.go | 2 +- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/cmd/any2anexoj-cli/main.go b/cmd/any2anexoj-cli/main.go index ae0fb89..08a4380 100644 --- a/cmd/any2anexoj-cli/main.go +++ b/cmd/any2anexoj-cli/main.go @@ -71,7 +71,7 @@ func run(ctx context.Context) error { } eg.Go(func() error { - return internal.BuildReport(ctx, reader, writer, selector) + return internal.BuildReport(ctx, reader, writer, internal.WithSelector(selector)) }) err = eg.Wait() diff --git a/internal/report.go b/internal/report.go index b8e5a59..1020fbc 100644 --- a/internal/report.go +++ b/internal/report.go @@ -51,12 +51,35 @@ type ReportWriter interface { Write(context.Context, ReportItem) error } +type optionals struct { + selector Selector +} + +func applyOptions(defaults optionals, opts []Option) optionals { + for _, opt := range opts { + opt(&defaults) + } + return defaults +} + +type Option func(*optionals) + +func WithSelector(s Selector) Option { + return func(o *optionals) { + o.selector = s + } +} + // Selector returns true if a record should be selected for processing, false otherwise. type Selector func(Record) bool // BuildReport reads records from a RecordReader and, if the record passes the Selector, it is // processed into the ReportWriter. -func BuildReport(ctx context.Context, reader RecordReader, writer ReportWriter, sel Selector) error { +func BuildReport(ctx context.Context, reader RecordReader, writer ReportWriter, options ...Option) error { + optionals := applyOptions(optionals{ + selector: Any(), + }, options) + buys := make(map[string]*FillerQueue) var buysCount, sellsCount int64 @@ -98,7 +121,7 @@ func BuildReport(ctx context.Context, reader RecordReader, writer ReportWriter, buys[rec.Symbol()] = buyQueue } - err = processRecord(ctx, buyQueue, rec, sel, writer) + err = processRecord(ctx, buyQueue, rec, optionals.selector, writer) if err != nil { return fmt.Errorf("processing record: %w", err) } @@ -109,10 +132,6 @@ func BuildReport(ctx context.Context, reader RecordReader, writer ReportWriter, // processRecord either adds buys to the queue or consumes buys from the queue when processing a // sell record. -// -// NOTE: Selectors are only applied when processing sell records for performance reasons. It's much -// cheaper to just accumulate buys and only actually inspect any records once a sell happens. This -// avoids potential network requests to for every single record. func processRecord(ctx context.Context, q *FillerQueue, rec Record, sel Selector, writer ReportWriter) error { slog.Debug( "Report: processing record", @@ -122,6 +141,9 @@ func processRecord(ctx context.Context, q *FillerQueue, rec Record, sel Selector switch rec.Kind() { case KindBuy: + // Selectors are only applied when processing sell records for performance reasons. It's much + // cheaper to just accumulate buys and only actually inspect any records once a sell happens. This + // avoids potential network requests to for every single record. q.Push(NewFiller(rec)) case KindSell: @@ -142,7 +164,8 @@ func processRecord(ctx context.Context, q *FillerQueue, rec Record, sel Selector return ErrInsufficientBoughtVolume } - // Since we don't apply selectors while processing buys we need to apply them here. + // Since we don't apply selectors while processing buys we need to apply them here, befre we + // actually use them. if !sel(buy) { continue } diff --git a/internal/report_test.go b/internal/report_test.go index 5c5d024..6145b6b 100644 --- a/internal/report_test.go +++ b/internal/report_test.go @@ -43,7 +43,7 @@ func TestBuildReport(t *testing.T) { Taxes: decimal.Decimal{}, })).Times(1) - gotErr := internal.BuildReport(t.Context(), reader, writer, internal.Any()) + gotErr := internal.BuildReport(t.Context(), reader, writer) if gotErr != nil { t.Fatalf("got unexpected err: %v", gotErr) }