handle some edge cases
Generate check / check-changes (pull_request) Successful in 41s
Quality / check-changes (pull_request) Successful in 42s
Generate check / verify-generate (pull_request) Successful in 48s
Quality / run-tests (pull_request) Successful in 49s

This commit is contained in:
2026-08-02 16:13:03 +01:00
parent 5fe47746fa
commit 18edd7d171
3 changed files with 75 additions and 5 deletions
+6 -3
View File
@@ -50,6 +50,9 @@ func (fs *FileStore) Load(ctx context.Context) (map[string]*FillerQueue, error)
}
return nil, fmt.Errorf("reading state file: %w", err)
}
if len(data) == 0 {
return make(map[string]*FillerQueue), nil
}
var s State
if err := json.Unmarshal(data, &s); err != nil {
@@ -74,7 +77,7 @@ func (fs *FileStore) Load(ctx context.Context) (map[string]*FillerQueue, error)
for symbol, persisted := range s.Queues {
q := new(FillerQueue)
for _, pf := range persisted {
rec, err := fs.serializer.UnmarshalRecord(ctx, pf.ReaderData)
rec, err := fs.serializer.UnmarshalRecord(ctx, pf.RecordData)
if err != nil {
return nil, fmt.Errorf(
"unmarshalling record for symbol %q: %w", symbol, err,
@@ -98,7 +101,7 @@ func (fs *FileStore) Save(ctx context.Context, queue map[string]*FillerQueue) er
}
for symbol, q := range queue {
if q == nil {
if q == nil || q.Len() == 0 {
continue
}
var persisted []persistedFiller
@@ -109,7 +112,7 @@ func (fs *FileStore) Save(ctx context.Context, queue map[string]*FillerQueue) er
return fmt.Errorf("marshalling record for symbol %q: %w", symbol, err)
}
persisted = append(persisted, persistedFiller{
ReaderData: data,
RecordData: data,
Quantity: f.Quantity(),
Price: f.Price(),
Filled: f.Filled(),
+68 -1
View File
@@ -19,7 +19,7 @@ import (
func TestFileStore_RoundTrip(t *testing.T) {
ctrl := gomock.NewController(t)
ser := roundTripSerializer(ctrl)
store, _ := newStore(t, "fake", ser)
store, path := newStore(t, "fake", ser)
original := map[string]*internal.FillerQueue{
"AAA": newQueue(
@@ -50,6 +50,73 @@ func TestFileStore_RoundTrip(t *testing.T) {
}
assertQueueEqual(t, symbol, gotQ, wantQ)
}
// Regression: the on-disk JSON key for the per-record blob must be
// "record_data" (renamed from "reader_data") so the field name stays
// honest about what it carries.
data, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read state file: %v", err)
}
if strings.Contains(string(data), `"reader_data"`) {
t.Errorf("saved state file still contains legacy key \"reader_data\"; want only \"record_data\"")
}
if !strings.Contains(string(data), `"record_data"`) {
t.Errorf("saved state file does not contain expected key \"record_data\"")
}
}
func TestFileStore_SaveSkipsEmptyQueue(t *testing.T) {
ctrl := gomock.NewController(t)
ser := roundTripSerializer(ctrl)
store, path := newStore(t, "fake", ser)
// A non-nil FillerQueue whose underlying list is nil — i.e. a symbol
// that was registered but never received a Push. Save must not panic
// when iterating and must not emit any entry for that symbol.
queues := map[string]*internal.FillerQueue{
"EMPTY": new(internal.FillerQueue),
"REAL": newQueue(newFiller(ctrl, "REAL", 5, 10, 0)),
}
if err := store.Save(t.Context(), queues); err != nil {
t.Fatalf("Save returned unexpected error: %v", err)
}
data, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read state file: %v", err)
}
body := string(data)
if strings.Contains(body, `"EMPTY"`) {
t.Errorf("saved state file contains entry for empty queue \"EMPTY\"; want it skipped")
}
if !strings.Contains(body, `"REAL"`) {
t.Errorf("saved state file missing expected entry for \"REAL\"")
}
}
func TestFileStore_LoadEmptyFileReturnsEmpty(t *testing.T) {
ctrl := gomock.NewController(t)
ser := roundTripSerializer(ctrl)
store, path := newStore(t, "fake", ser)
// Pre-create the state file as a zero-byte file. Load must treat this
// the same as a missing file rather than failing JSON unmarshal.
if err := os.WriteFile(path, []byte{}, 0o644); err != nil {
t.Fatalf("write empty state file: %v", err)
}
queues, err := store.Load(t.Context())
if err != nil {
t.Fatalf("Load returned unexpected error for empty file: %v", err)
}
if queues == nil {
t.Fatalf("Load returned nil map; want empty map")
}
if len(queues) != 0 {
t.Fatalf("Load returned %d entries; want 0", len(queues))
}
}
func TestFileStore_LoadMissingFileReturnsEmpty(t *testing.T) {
+1 -1
View File
@@ -21,7 +21,7 @@ type State struct {
// Record-specific data is kept as opaque bytes so the internal package does
// not need to know about any broker package's concrete Record type.
type persistedFiller struct {
ReaderData []byte `json:"reader_data"`
RecordData []byte `json:"record_data"`
Quantity decimal.Decimal `json:"quantity"`
Price decimal.Decimal `json:"price"`
Filled decimal.Decimal `json:"filled"`