MCPcopy
hub / github.com/keploy/keploy / StoreMocks

Method StoreMocks

pkg/service/agent/agent.go:641–694  ·  view source on GitHub ↗

StoreMocks stores the filtered and unfiltered mocks for a client ID. Unification (Phase 1): every mock is run through DeriveLifetime on entry so TestModeInfo.Lifetime is populated before any matcher reads it. This is a second safety-net — the mockdb disk loader already derives at load time, but Sto

(ctx context.Context, filtered []*models.Mock, unfiltered []*models.Mock)

Source from the content-addressed store, hash-verified

639// deep copy here unless a concrete mutation-safety regression lands
640// first.
641func (a *Agent) StoreMocks(ctx context.Context, filtered []*models.Mock, unfiltered []*models.Mock) error {
642 storage := &ClientMockStorage{
643 filtered: make([]*models.Mock, len(filtered)),
644 unfiltered: make([]*models.Mock, len(unfiltered)),
645 }
646
647 // Shallow copy the slices — only the outer backing array is
648 // duplicated, the *models.Mock pointers are shared with the
649 // caller's slices. This is INTENTIONAL and load-bearing: matchers
650 // look up mocks via pointer identity in MockManager's trees and
651 // per-connID pools, and HitCount/Lifetime are bumped on the shared
652 // Mock object so observability is consistent across the stack (see
653 // the caveat block before this function for the full rationale).
654 // Do NOT switch to a deep copy without coordinated updates at
655 // every downstream site.
656 copy(storage.filtered, filtered)
657 copy(storage.unfiltered, unfiltered)
658
659 // Derive Lifetime once per mock before they enter the runtime pool.
660 // Idempotent: DeriveLifetime short-circuits when the Lifetime
661 // field is already set (i.e. the disk loader has already run),
662 // so re-deriving here is safe and never double-counts the
663 // legacyKindFallbackFires telemetry.
664 for _, m := range storage.filtered {
665 if m != nil {
666 m.DeriveLifetime()
667 }
668 }
669 for _, m := range storage.unfiltered {
670 if m != nil {
671 m.DeriveLifetime()
672 }
673 }
674
675 a.clientMocks.Store(uint64(0), storage)
676
677 // Compute the freeze anchor as the earliest ReqTimestampMock across the
678 // stored mocks and forward it to AgentHooks. The hook implementation
679 // decides whether to apply it (a no-op when freezeTime is off). Doing
680 // this here, alongside the StoreMocks write, guarantees the anchor is
681 // known to the hook before BeforeTestRun fires — i.e. before the user
682 // app's first datetime.now() call — which is what closes the bootstrap
683 // gap that lets boto3 / JWT libs see "now > recorded Expiration" and
684 // kill the worker.
685 if anchor := earliestReqTimestamp(storage.filtered, storage.unfiltered); !anchor.IsZero() {
686 if err := ActiveHooks.SetFreezeAnchor(ctx, anchor); err != nil {
687 a.logger.Warn("SetFreezeAnchor hook returned error",
688 zap.Error(err), zap.Time("anchor", anchor))
689 }
690 }
691
692 a.logger.Debug("Successfully stored mocks for client")
693 return nil
694}
695
696// earliestReqTimestamp returns the earliest non-zero ReqTimestampMock seen
697// across the supplied mock slices, or a zero time.Time if none are set.

Callers

nothing calls this directly

Calls 7

earliestReqTimestampFunction · 0.85
DeriveLifetimeMethod · 0.80
IsZeroMethod · 0.80
SetFreezeAnchorMethod · 0.65
DebugMethod · 0.65
StoreMethod · 0.45
ErrorMethod · 0.45

Tested by

no test coverage detected