auth_cache_invalidation_profit_integration_test.go 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. //go:build integration
  2. package repository
  3. // migration 193 回归:groups 触发器的 durable 失效监视清单必须覆盖利润控制
  4. // 配置及 D 依赖的分组计价字段(正常后台保存走 InvalidateAuthCacheByGroupID 即时失效,触发器兜底
  5. // 直改 SQL / 更新与失效之间崩溃等 out-of-band 场景)。
  6. import (
  7. "context"
  8. "crypto/sha256"
  9. "encoding/hex"
  10. "fmt"
  11. "testing"
  12. "time"
  13. "github.com/Wei-Shaw/sub2api/internal/service"
  14. "github.com/stretchr/testify/require"
  15. )
  16. func TestAuthCacheInvalidationTrigger_ProfitControlColumns(t *testing.T) {
  17. ctx := context.Background()
  18. suffix := time.Now().UnixNano()
  19. group := mustCreateGroup(t, integrationEntClient, &service.Group{
  20. Name: fmt.Sprintf("profit-trigger-group-%d", suffix), Platform: service.PlatformOpenAI, RateMultiplier: 1,
  21. })
  22. user := mustCreateUser(t, integrationEntClient, &service.User{
  23. Email: fmt.Sprintf("profit-trigger-%d@example.com", suffix), Concurrency: 5,
  24. })
  25. groupID := group.ID
  26. keyValue := fmt.Sprintf("sk-profit-trigger-%d", suffix)
  27. apiKeyRepo := NewAPIKeyRepository(integrationEntClient, integrationDB)
  28. key := &service.APIKey{UserID: user.ID, GroupID: &groupID, Key: keyValue, Name: "profit-trigger", Status: service.StatusActive}
  29. require.NoError(t, apiKeyRepo.Create(ctx, key))
  30. sum := sha256.Sum256([]byte(keyValue))
  31. cacheKey := hex.EncodeToString(sum[:])
  32. clear := func() {
  33. _, err := integrationDB.ExecContext(ctx, "DELETE FROM auth_cache_invalidation_outbox WHERE cache_key = $1", cacheKey)
  34. require.NoError(t, err)
  35. }
  36. count := func() int {
  37. var value int
  38. require.NoError(t, integrationDB.QueryRowContext(ctx,
  39. "SELECT COUNT(*) FROM auth_cache_invalidation_outbox WHERE cache_key = $1", cacheKey).Scan(&value))
  40. return value
  41. }
  42. clear()
  43. t.Cleanup(clear)
  44. t.Cleanup(func() {
  45. _, err := integrationDB.ExecContext(ctx, "DELETE FROM api_keys WHERE id = $1", key.ID)
  46. require.NoError(t, err)
  47. _, err = integrationDB.ExecContext(ctx, "DELETE FROM users WHERE id = $1", user.ID)
  48. require.NoError(t, err)
  49. _, err = integrationDB.ExecContext(ctx, "DELETE FROM groups WHERE id = $1", group.ID)
  50. require.NoError(t, err)
  51. })
  52. _, err := integrationDB.ExecContext(ctx, "UPDATE groups SET name = name || '-cosmetic' WHERE id = $1", group.ID)
  53. require.NoError(t, err)
  54. require.Zero(t, count(), "cosmetic 更新不得入队(既有语义回归)")
  55. _, err = integrationDB.ExecContext(ctx, "UPDATE groups SET profit_control_enabled = NOT profit_control_enabled WHERE id = $1", group.ID)
  56. require.NoError(t, err)
  57. require.Equal(t, 1, count(), "profit_control_enabled 变更必须入队")
  58. clear()
  59. _, err = integrationDB.ExecContext(ctx, "UPDATE groups SET profit_min_margin = 0.3 WHERE id = $1", group.ID)
  60. require.NoError(t, err)
  61. require.Equal(t, 1, count(), "profit_min_margin 变更必须入队")
  62. clear()
  63. _, err = integrationDB.ExecContext(ctx, "UPDATE groups SET profit_safety_buffer = 0.02 WHERE id = $1", group.ID)
  64. require.NoError(t, err)
  65. require.Equal(t, 1, count(), "profit_safety_buffer 变更必须入队")
  66. clear()
  67. _, err = integrationDB.ExecContext(ctx, "UPDATE groups SET profit_min_margin = profit_min_margin WHERE id = $1", group.ID)
  68. require.NoError(t, err)
  69. require.Zero(t, count(), "利润字段无实际变化的 UPDATE 不得入队")
  70. for name, update := range map[string]string{
  71. "platform": "platform = 'anthropic'",
  72. "subscription_type": "subscription_type = 'subscription'",
  73. "rate_multiplier": "rate_multiplier = 0.9",
  74. "peak_rate_enabled": "peak_rate_enabled = true",
  75. "peak_start": "peak_start = '08:00'",
  76. "peak_end": "peak_end = '09:00'",
  77. "peak_rate_multiplier": "peak_rate_multiplier = 1.2",
  78. } {
  79. t.Run(name, func(t *testing.T) {
  80. clear()
  81. _, err := integrationDB.ExecContext(ctx, "UPDATE groups SET "+update+" WHERE id = $1", group.ID)
  82. require.NoError(t, err)
  83. require.Equal(t, 1, count(), name+" 变更必须入队")
  84. })
  85. }
  86. }