TestCacheVolatileNestedWithNonVolatile verifies that a volatile exec followed by a non-volatile exec produces correct cache behavior: changing only the volatile value should reuse the volatile exec but still run the non-volatile exec if its non-volatile inputs changed.
(t *testing.T)
| 970 | // volatile value should reuse the volatile exec but still run the non-volatile |
| 971 | // exec if its non-volatile inputs changed. |
| 972 | func TestCacheVolatileNestedWithNonVolatile(t *testing.T) { |
| 973 | t.Parallel() |
| 974 | |
| 975 | baseCtx := cacheTestContext(t.Context()) |
| 976 | cacheIface, err := NewCache(baseCtx, "", nil, nil) |
| 977 | assert.NilError(t, err) |
| 978 | c := cacheIface |
| 979 | ctx := ContextWithCache(baseCtx, c) |
| 980 | srv := cacheTestServer(t) |
| 981 | |
| 982 | type volatileArgs struct { |
| 983 | Slot String `name:"slot"` |
| 984 | Value String `name:"value"` |
| 985 | } |
| 986 | |
| 987 | var volatileCalls atomic.Int32 |
| 988 | Fields[cacheTestQuery]{ |
| 989 | NodeFuncWithDynamicInputs( |
| 990 | "volatileNestedParent", |
| 991 | func(ctx context.Context, _ ObjectResult[cacheTestQuery], args volatileArgs) (Result[*cacheTestObject], error) { |
| 992 | if got := string(args.Value); got != cacheTestVolatileValueSentinel { |
| 993 | return Result[*cacheTestObject]{}, fmt.Errorf("resolver saw unrewritten volatile value %q", got) |
| 994 | } |
| 995 | leaf, err := cacheTestSessionResourceLeaf(ctx, cacheTestVolatileSessionResourceHandle(string(args.Slot))) |
| 996 | if err != nil { |
| 997 | return Result[*cacheTestObject]{}, err |
| 998 | } |
| 999 | return NewResultForCurrentCall(ctx, &cacheTestObject{ |
| 1000 | Value: int(volatileCalls.Add(1)), |
| 1001 | dependencyResults: []AnyResult{leaf}, |
| 1002 | }) |
| 1003 | }, |
| 1004 | func(ctx context.Context, _ ObjectResult[cacheTestQuery], args volatileArgs, req *CallRequest) error { |
| 1005 | cache, err := EngineCache(ctx) |
| 1006 | if err != nil { |
| 1007 | return err |
| 1008 | } |
| 1009 | clientMetadata, err := engine.ClientMetadataFromContext(ctx) |
| 1010 | if err != nil { |
| 1011 | return err |
| 1012 | } |
| 1013 | handle := cacheTestVolatileSessionResourceHandle(string(args.Slot)) |
| 1014 | if err := cache.BindSessionResource(ctx, clientMetadata.SessionID, clientMetadata.ClientID, handle, string(args.Value)); err != nil { |
| 1015 | return err |
| 1016 | } |
| 1017 | return req.SetArgInput(ctx, "value", NewString(cacheTestVolatileValueSentinel), false) |
| 1018 | }, |
| 1019 | ), |
| 1020 | }.Install(srv) |
| 1021 | |
| 1022 | type regularArgs struct { |
| 1023 | Marker String `name:"marker"` |
| 1024 | } |
| 1025 | var regularCalls atomic.Int32 |
| 1026 | Fields[*cacheTestObject]{ |
| 1027 | NodeFunc("regularChild", func(ctx context.Context, self ObjectResult[*cacheTestObject], args regularArgs) (Result[*cacheTestObject], error) { |
| 1028 | return NewResultForCurrentCall(ctx, &cacheTestObject{ |
| 1029 | Value: int(regularCalls.Add(1)), |
nothing calls this directly
no test coverage detected