diff --git a/internal/modules/stats/startup.go b/internal/modules/stats/startup.go index dbd78bf..35ea8ec 100644 --- a/internal/modules/stats/startup.go +++ b/internal/modules/stats/startup.go @@ -24,7 +24,7 @@ const ( usageMigrationName = "stats-usage-v2" usageMigrationKey = "migration:" + usageMigrationName - commandHistoryMigrationName = "stats-command-history-v1" + commandHistoryMigrationName = "stats-command-history-v2" commandHistoryMigrationKey = "migration:" + commandHistoryMigrationName ) @@ -34,6 +34,12 @@ type commandRename struct { } var commandRenames = []commandRename{ + {Old: "trade_topup", New: "stock_topup"}, + {Old: "trade_buy", New: "stock_buy"}, + {Old: "trade_sell", New: "stock_sell"}, + {Old: "trade_income_stock", New: "stock_bonus"}, + {Old: "trade_income_vnd", New: "stock_dividend"}, + {Old: "trade_stats", New: "stock_portfolio"}, {Old: "lolschedule", New: "lol"}, {Old: "lolschedule_week", New: "lol_this_week"}, {Old: "lolschedule_subscribe", New: "lol_subscribe"}, @@ -48,6 +54,9 @@ var commandRenames = []commandRename{ var deletedCommandNames = []string{ "lolschedule_today", + "trade_income_events", + "trade_convert", + "stock_income_events", "wc_today", "stock_convert", } diff --git a/internal/modules/stats/startup_mongo_test.go b/internal/modules/stats/startup_mongo_test.go index 9fe1cd8..29223ba 100644 --- a/internal/modules/stats/startup_mongo_test.go +++ b/internal/modules/stats/startup_mongo_test.go @@ -42,12 +42,25 @@ func TestInitStore_MongoCreatesIndexesAndMigratesLegacy(t *testing.T) { systemColl := provider.Collection(systemstate.CollectionName) legacyCounts := storage.Typed[legacyCountEntry](statsColl) legacyUsers := storage.Typed[legacyUserEntry](statsColl) + sys := systemstate.New(systemColl) + if err := sys.Put(ctx, "migration:stats-command-history-v1", systemstate.Record{ + Kind: "migration", + Name: "stats-command-history-v1", + Status: "done", + Count: 2, + UpdatedAt: 1, + }); err != nil { + t.Fatalf("seed v1 marker: %v", err) + } if err := legacyCounts.Put(ctx, legacyCountPrefix+"ping", legacyCountEntry{N: 2}); err != nil { t.Fatalf("legacy count: %v", err) } if err := legacyCounts.Put(ctx, legacyCountPrefix+"gold_stats", legacyCountEntry{N: 4}); err != nil { t.Fatalf("legacy renamed count: %v", err) } + if err := legacyCounts.Put(ctx, legacyCountPrefix+"trade_stats", legacyCountEntry{N: 6}); err != nil { + t.Fatalf("legacy trade count: %v", err) + } if err := legacyUsers.Put(ctx, legacyUserPrefix+"7", legacyUserEntry{Username: "alice", N: 1}); err != nil { t.Fatalf("legacy user: %v", err) } @@ -66,6 +79,7 @@ func TestInitStore_MongoCreatesIndexesAndMigratesLegacy(t *testing.T) { assertUsageEntry(t, usageDocs, usageKey("ping", 7), usageEntry{Cmd: "ping", UserID: 7, Username: "alice", N: 1}) assertUsageEntry(t, usageDocs, usageKey("ping", 0), usageEntry{Cmd: "ping", N: 1}) assertUsageEntry(t, usageDocs, usageKey("gold_portfolio", 0), usageEntry{Cmd: "gold_portfolio", N: 4}) + assertUsageEntry(t, usageDocs, usageKey("stock_portfolio", 0), usageEntry{Cmd: "stock_portfolio", N: 6}) assertUsageEntry(t, usageDocs, usageKey("stock_convert", 7), usageEntry{Cmd: "stock_convert", UserID: 7, Username: "alice", N: 3, Deleted: true}) rawStatsColl, ok := storage.MongoCollection(statsColl) @@ -97,13 +111,12 @@ func TestInitStore_MongoCreatesIndexesAndMigratesLegacy(t *testing.T) { } } - sys := systemstate.New(systemColl) rec, ok, err := sys.Get(ctx, commandHistoryMigrationKey) if err != nil || !ok { t.Fatalf("command history marker ok=%v err=%v", ok, err) } - if rec.Status != "done" || rec.Count != 2 { - t.Fatalf("command history marker = %+v, want done count 2", rec) + if rec.Status != "done" || rec.Count != 3 { + t.Fatalf("command history marker = %+v, want done count 3", rec) } rawDoc := bson.M{} diff --git a/internal/modules/stats/stats_test.go b/internal/modules/stats/stats_test.go index 084c284..134fb41 100644 --- a/internal/modules/stats/stats_test.go +++ b/internal/modules/stats/stats_test.go @@ -318,15 +318,34 @@ func TestInitStore_MigratesCommandHistoryAndMarksDeleted(t *testing.T) { statsColl := provider.Collection("stats") systemColl := provider.Collection(systemstate.CollectionName) usageDocs := storage.Typed[usageEntry](statsColl) + sys := systemstate.New(systemColl) + + if err := sys.Put(ctx, "migration:stats-command-history-v1", systemstate.Record{ + Kind: "migration", + Name: "stats-command-history-v1", + Status: "done", + Count: 5, + UpdatedAt: 1, + }); err != nil { + t.Fatalf("seed v1 marker: %v", err) + } seed := map[string]usageEntry{ usageKey("gold_stats", 0): {Cmd: "gold_stats", N: 2}, usageKey("gold_portfolio", 0): {Cmd: "gold_portfolio", N: 5}, + usageKey("trade_topup", 0): {Cmd: "trade_topup", N: 6}, + usageKey("trade_stats", 0): {Cmd: "trade_stats", N: 9}, + usageKey("stock_portfolio", 0): {Cmd: "stock_portfolio", N: 1}, + usageKey("trade_income_stock", 7): {Cmd: "trade_income_stock", UserID: 7, Username: "alice", N: 5}, usageKey("stock_income_stock", 7): {Cmd: "stock_income_stock", UserID: 7, Username: "alice", N: 3}, usageKey("stock_bonus", 7): {Cmd: "stock_bonus", UserID: 7, Username: "alice", N: 4}, usageKey("lolschedule_week", 8): {Cmd: "lolschedule_week", UserID: 8, Username: "bob", N: 1}, usageKey("lolschedule_today", 0): {Cmd: "lolschedule_today", N: 9}, + usageKey("trade_income_events", 8): {Cmd: "trade_income_events", UserID: 8, Username: "bob", N: 3}, + usageKey("trade_convert", 7): {Cmd: "trade_convert", UserID: 7, Username: "alice", N: 4}, + usageKey("stock_income_events", 0): {Cmd: "stock_income_events", N: 5}, usageKey("stock_convert", 7): {Cmd: "stock_convert", UserID: 7, Username: "alice", N: 2}, + usageKey("trade_stats_extra", 7): {Cmd: "trade_stats_extra", UserID: 7, Username: "alice", N: 99}, usageKey("stock_convert_extra", 7): {Cmd: "stock_convert_extra", UserID: 7, Username: "alice", N: 99}, usageKey("lolschedule_weekly", 10): {Cmd: "lolschedule_weekly", UserID: 10, Username: "carol", N: 99}, usageKey("stock_income_stocked", 11): {Cmd: "stock_income_stocked", UserID: 11, Username: "dan", N: 99}, @@ -342,16 +361,25 @@ func TestInitStore_MigratesCommandHistoryAndMarksDeleted(t *testing.T) { } assertUsageEntry(t, usageDocs, usageKey("gold_portfolio", 0), usageEntry{Cmd: "gold_portfolio", N: 7}) - assertUsageEntry(t, usageDocs, usageKey("stock_bonus", 7), usageEntry{Cmd: "stock_bonus", UserID: 7, Username: "alice", N: 7}) + assertUsageEntry(t, usageDocs, usageKey("stock_topup", 0), usageEntry{Cmd: "stock_topup", N: 6}) + assertUsageEntry(t, usageDocs, usageKey("stock_portfolio", 0), usageEntry{Cmd: "stock_portfolio", N: 10}) + assertUsageEntry(t, usageDocs, usageKey("stock_bonus", 7), usageEntry{Cmd: "stock_bonus", UserID: 7, Username: "alice", N: 12}) assertUsageEntry(t, usageDocs, usageKey("lol_this_week", 8), usageEntry{Cmd: "lol_this_week", UserID: 8, Username: "bob", N: 1}) assertUsageEntry(t, usageDocs, usageKey("lolschedule_today", 0), usageEntry{Cmd: "lolschedule_today", N: 9, Deleted: true}) + assertUsageEntry(t, usageDocs, usageKey("trade_income_events", 8), usageEntry{Cmd: "trade_income_events", UserID: 8, Username: "bob", N: 3, Deleted: true}) + assertUsageEntry(t, usageDocs, usageKey("trade_convert", 7), usageEntry{Cmd: "trade_convert", UserID: 7, Username: "alice", N: 4, Deleted: true}) + assertUsageEntry(t, usageDocs, usageKey("stock_income_events", 0), usageEntry{Cmd: "stock_income_events", N: 5, Deleted: true}) assertUsageEntry(t, usageDocs, usageKey("stock_convert", 7), usageEntry{Cmd: "stock_convert", UserID: 7, Username: "alice", N: 2, Deleted: true}) + assertUsageEntry(t, usageDocs, usageKey("trade_stats_extra", 7), usageEntry{Cmd: "trade_stats_extra", UserID: 7, Username: "alice", N: 99}) assertUsageEntry(t, usageDocs, usageKey("stock_convert_extra", 7), usageEntry{Cmd: "stock_convert_extra", UserID: 7, Username: "alice", N: 99}) assertUsageEntry(t, usageDocs, usageKey("lolschedule_weekly", 10), usageEntry{Cmd: "lolschedule_weekly", UserID: 10, Username: "carol", N: 99}) assertUsageEntry(t, usageDocs, usageKey("stock_income_stocked", 11), usageEntry{Cmd: "stock_income_stocked", UserID: 11, Username: "dan", N: 99}) for _, key := range []string{ usageKey("gold_stats", 0), + usageKey("trade_topup", 0), + usageKey("trade_stats", 0), + usageKey("trade_income_stock", 7), usageKey("stock_income_stock", 7), usageKey("lolschedule_week", 8), } { @@ -360,19 +388,19 @@ func TestInitStore_MigratesCommandHistoryAndMarksDeleted(t *testing.T) { } } - sys := systemstate.New(systemColl) rec, ok, err := sys.Get(ctx, commandHistoryMigrationKey) if err != nil || !ok { t.Fatalf("command history marker ok=%v err=%v", ok, err) } - if rec.Status != "done" || rec.Count != 5 { - t.Fatalf("command history marker = %+v, want done count 5", rec) + if rec.Status != "done" || rec.Count != 11 { + t.Fatalf("command history marker = %+v, want done count 11", rec) } if err := InitStore(ctx, statsColl, systemColl); err != nil { t.Fatalf("InitStore second run: %v", err) } assertUsageEntry(t, usageDocs, usageKey("gold_portfolio", 0), usageEntry{Cmd: "gold_portfolio", N: 7}) + assertUsageEntry(t, usageDocs, usageKey("stock_portfolio", 0), usageEntry{Cmd: "stock_portfolio", N: 10}) } func TestStatsViewsFilterDeletedLegacyRows(t *testing.T) {