Skip to content

Commit d108437

Browse files
Option to respect range during cache streaming
The core cache API allows for cache items to be concurrently streamed to / from the cache. If: - The size of the cached item's body was not provided by the writer - The reader requests a specific range of the cached item's body (`to_stream_from_range`) - The writer and reader are concurrent, i.e. the body is streamed from one to the other then today, the core cache API will ignore the requested range and provide the whole body. There is no explicit notification that the whole body is provided instead of a range. In this SDK release, this remains the default behavior. However, the lookup options struct now now offers an `AlwaysUseRequestedRange` option. If set to true, body reads conducted as part of this lookup/transaction will always use the requested range, even when streaming. If false, the behavior is unchanged (as above). In a future SDK release, the default behavior will change to "always use requested range".
1 parent 0b39b3c commit d108437

File tree

5 files changed

+72
-2
lines changed

5 files changed

+72
-2
lines changed

cache/core/core.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,16 @@ type LookupOptions struct {
258258
// To indicates the ending offset to read from the cached object. A
259259
// value of 0 means to read to the end of the object.
260260
To uint64
261+
262+
// By default, if:
263+
// - The size of the cached item's body was not provided by the writer
264+
// - The reader requests a specific range of the cached item's body (`From` and `To` are set)
265+
// - The writer and reader are concurrent, i.e. the body is streamed from one to the other
266+
// then today, the core cache API will ignore the requested range and provide the whole body.
267+
//
268+
// Setting this flag provides the more intuitive behavior: the range will be respected
269+
// during streaming as well.
270+
AlwaysUseRequestedRange bool
261271
}
262272

263273
func abiLookupOptions(opts LookupOptions) (fastly.CacheLookupOptions, error) {
@@ -272,6 +282,8 @@ func abiLookupOptions(opts LookupOptions) (fastly.CacheLookupOptions, error) {
272282
abiOpts.SetRequest(req)
273283
}
274284

285+
abiOpts.SetAlwaysUseRequestedRange(opts.AlwaysUseRequestedRange)
286+
275287
return abiOpts, nil
276288
}
277289

cache/core/core_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,46 @@ func ExampleFound_GetRange() {
208208

209209
fmt.Printf("The cached value was: %s", cachedStr)
210210
}
211+
212+
func ExampleLookupOptions_AlwaysUseRequestedRange() {
213+
const (
214+
key = "my_key"
215+
contents = "my cached object"
216+
)
217+
218+
// Start an insert; this will be concurrent with the read.
219+
// Data written to this handle is streamed into the Fastly cache.
220+
w, err := core.Insert([]byte(key), core.WriteOptions{
221+
TTL: time.Hour,
222+
SurrogateKeys: []string{key},
223+
Length: uint64(len(contents)),
224+
})
225+
if err != nil {
226+
panic(err)
227+
}
228+
229+
// With the write still outstanding, start a lookup for a specific range.
230+
f, err := core.Lookup([]byte("my_key"), core.LookupOptions{
231+
From: 3,
232+
To: 8,
233+
AlwaysUseRequestedRange: true,
234+
})
235+
if err != nil {
236+
panic(err)
237+
}
238+
239+
// Write and flush:
240+
if _, err := io.WriteString(w, contents); err != nil {
241+
panic(err)
242+
}
243+
244+
cachedStr, err := io.ReadAll(f.Body)
245+
if err != nil {
246+
panic(err)
247+
}
248+
if string(cachedStr) != "cached" {
249+
panic(fmt.Sprintf("got: %q, want: %q", cachedStr, "cached object"))
250+
}
251+
252+
fmt.Printf("The cached value was: %s", cachedStr)
253+
}

internal/abi/fastly/cache_guest.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ func (o *CacheLookupOptions) SetRequest(req *HTTPRequest) {
2121
o.mask |= cacheLookupOptionsMaskRequestHeaders
2222
}
2323

24+
func (o *CacheLookupOptions) SetAlwaysUseRequestedRange(alwaysUseRequestedRange bool) {
25+
if alwaysUseRequestedRange {
26+
o.mask |= cacheLookupOptionsMaskAlwaysUseRequestedRange
27+
} else {
28+
o.mask &= ^cacheLookupOptionsMaskAlwaysUseRequestedRange
29+
}
30+
}
31+
2432
type CacheGetBodyOptions struct {
2533
opts cacheGetBodyOptions
2634
mask cacheGetBodyOptionsMask

internal/abi/fastly/hostcalls_noguest.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,10 @@ func (o *CacheLookupOptions) SetRequest(req *HTTPRequest) error {
425425
return fmt.Errorf("not implemented")
426426
}
427427

428+
func (o *CacheLookupOptions) SetAlwaysUseRequestedRange(alwaysUseRequestedRange bool) error {
429+
return fmt.Errorf("not implemented")
430+
}
431+
428432
func (o *CacheGetBodyOptions) From(from uint64) error {
429433
return fmt.Errorf("not implemented")
430434
}

internal/abi/fastly/types.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -721,13 +721,16 @@ type cacheLookupOptions struct {
721721
// (flags (@witx repr u32)
722722
// $reserved
723723
// $request_headers
724+
// $service_id
725+
// $always_use_requested_range
724726
// )
725727
// )
726728
type cacheLookupOptionsMask prim.U32
727729

728730
const (
729-
cacheLookupOptionsMaskReserved cacheLookupOptionsMask = 0b0000_0001 // $reserved
730-
cacheLookupOptionsMaskRequestHeaders cacheLookupOptionsMask = 0b0000_0010 // $request_headers
731+
cacheLookupOptionsMaskReserved cacheLookupOptionsMask = 0b0000_0001 // $reserved
732+
cacheLookupOptionsMaskRequestHeaders cacheLookupOptionsMask = 0b0000_0010 // $request_headers
733+
cacheLookupOptionsMaskAlwaysUseRequestedRange cacheLookupOptionsMask = 0b0000_1000 // $always_use_requested_range
731734
)
732735

733736
// witx:

0 commit comments

Comments
 (0)