---------------- MockManager (kind-aware) ---------------- Lock-ordering invariant (MUST be preserved to avoid deadlock): swapMu → treesMu → windowMu swapMu → revMu (SetMocksWithWindow calls Set*Mocks which bump revisions; revMu is a leaf lock —
| 35 | // consistency must use the atomic variants above. |
| 36 | |
| 37 | type MockManager struct { |
| 38 | // legacy "all" trees (kept for compatibility with existing callers) |
| 39 | filtered *TreeDb |
| 40 | unfiltered *TreeDb |
| 41 | |
| 42 | // startup tier (Wave 2) holds app-bootstrap traffic recorded BEFORE |
| 43 | // the first test window fires — Flyway migrations, Hibernate |
| 44 | // metadata-boot queries, HikariCP pool validation, driver-handshake |
| 45 | // SQL. It is strictly disjoint from the session tier (`unfiltered`) |
| 46 | // and from the per-test tier (`filtered`): every mock lives in |
| 47 | // exactly one of the three trees. |
| 48 | // |
| 49 | // Populated by SetMocksWithWindow when a mock's ReqTimestampMock |
| 50 | // predates firstWindowStart; queried via GetStartupMocks. The |
| 51 | // deprecated GetSessionMocks union shim concatenates the startup |
| 52 | // walk + the session walk so legacy parsers keep seeing startup |
| 53 | // mocks in their "session" snapshot until they migrate. |
| 54 | startup *TreeDb |
| 55 | |
| 56 | // global revision (legacy) |
| 57 | rev uint64 |
| 58 | |
| 59 | // NEW: per-kind revisions |
| 60 | revMu sync.RWMutex |
| 61 | revByKind map[models.Kind]*uint64 |
| 62 | |
| 63 | // NEW: per-kind trees (guarded by treesMu) |
| 64 | treesMu sync.RWMutex |
| 65 | filteredByKind map[models.Kind]*TreeDb |
| 66 | unfilteredByKind map[models.Kind]*TreeDb |
| 67 | |
| 68 | logger *zap.Logger |
| 69 | |
| 70 | // consumedMu guards consumedList and consumedIndex. |
| 71 | // consumedList records MockState entries in the order they were first |
| 72 | // intercepted from the network (first call to flagMockAsUsed wins the |
| 73 | // position; subsequent calls for the same name update the state in-place |
| 74 | // without changing order). |
| 75 | consumedMu sync.Mutex |
| 76 | consumedList []models.MockState |
| 77 | consumedIndex map[string]int |
| 78 | |
| 79 | // Optimized lookup maps |
| 80 | statelessFiltered map[models.Kind]map[string][]*models.Mock |
| 81 | statelessUnfiltered map[models.Kind]map[string][]*models.Mock |
| 82 | |
| 83 | // windowMu guards windowStart/windowEnd. They bound the REQUEST-time |
| 84 | // window for the outer HTTP/gRPC test currently being replayed; parsers |
| 85 | // use them via GetFilteredMocksInWindow to reject non-config mocks whose |
| 86 | // recorded REQUEST timestamp falls outside the window. Recorded |
| 87 | // responses may legitimately extend past windowEnd (downstream async |
| 88 | // completion is normal), so response containment is NOT enforced — only |
| 89 | // mocks with response timestamps earlier than their request timestamps |
| 90 | // (inconsistent recordings) are dropped as a sanity check. |
| 91 | // Zero values mean "no window set", in which case GetFilteredMocksInWindow |
| 92 | // falls back to GetFilteredMocks behaviour. |
| 93 | windowMu sync.RWMutex |
| 94 | windowStart time.Time |
nothing calls this directly
no outgoing calls
no test coverage detected