Transaction

Structin corecompute-sdk-go v1.11.0View source
type Transaction struct {
// contains filtered or unexported fields
}

Transaction represents a construct to coordinate concurrent actions for the same cache key.

Transactions incorporate concepts of request collapsing and revalidation, though at a lower level that does not automatically interpret HTTP semantics.

Request collapsing

If there are multiple concurrent calls to NewTransaction for the same object and that object is not present, only one of the callers will be instructed to insert the item into the cache as part of the transaction. The other callers will block until the metadata for the object has been inserted, and can then begin streaming its contents out of the cache at the same time that the inserting caller streams them into the cache.

Revalidation

Similarly, if an item is usable but stale, and multiple callers attempt a lookup concurrently, they will all be given access to the stale item, but only one will be designated to perform an update (or insertion) to freshen the item in the cache.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
useFoundItem := func(f *core.Found) {
}
buildContents := func() []byte {
return []byte("hello world!")
}
shouldReplace := func(f *core.Found, contents []byte) bool {
return true
}
tx, err := core.NewTransaction([]byte("my_key"), core.LookupOptions{})
if err != nil {
panic(err)
}
defer tx.Close()
f, err := tx.Found()
switch err {
case nil:
useFoundItem(f)
if tx.MustInsertOrUpdate() {
contents := buildContents()
if shouldReplace(f, contents) {
w, err := tx.Insert(core.WriteOptions{
TTL: time.Hour,
SurrogateKeys: []string{"my_key"},
Length: uint64(len(contents)),
})
if err != nil {
panic(err)
}
if _, err := w.Write(contents); err != nil {
panic(err)
}
if err := w.Close(); err != nil {
panic(err)
}
} else {
if err := tx.Update(core.WriteOptions{
TTL: time.Hour,
SurrogateKeys: []string{"my_key"},
}); err != nil {
panic(err)
}
}
}
case core.ErrNotFound:
if tx.MustInsert() {
contents := buildContents()
w, f, err := tx.InsertAndStreamBack(core.WriteOptions{
TTL: time.Hour,
SurrogateKeys: []string{"my_key"},
Length: uint64(len(contents)),
})
if err != nil {
panic(err)
}
if _, err := w.Write(contents); err != nil {
panic(err)
}
if err := w.Close(); err != nil {
panic(err)
}
useFoundItem(f)
} else {
panic(err)
}
default:
panic(err)
}

Methods

func (t *Transaction) Cancel() error

Cancel terminates the obligation to provide an object to the cache.

If there are concurrent transactional lookups that were blocked waiting on this client to provide the item, one of them will be chosen to be unblocked and given the Transaction.MustInsertOrUpdate obligation.

Cancel does not close the transaction. Callers must still call Close to end the transaction and cleanup resources associated with it.

Returns

error
func (t *Transaction) Close() error

Close ends the transaction and cleans up resources associated with it.

Returns

error
func (t *Transaction) Found() (*Found, error)

Found returns information about the found cached object, if one is available. If there is no cached object, [ErrNotFound] is returned.

Even if an object is found, the cache item might be stale and require updating. Use Transaction.MustInsertOrUpdate to determine whether this transaction client is expected to update the cached object.

Returns

(*Found, error)
func (t *Transaction) Insert(opts WriteOptions) (WriteCloseAbandoner, error)

Insert creates a WriteCloseAbandoner used for inserting an object into the cache for this transaction's key. For the insertion to complete successfully, the object must be fully written to the writer and its Close method called.

If Close is not called, or the writer's Abandon method is called, the insertion is incomplete and any concurrent lookups that may be reading from the object as it is streamed into the cache may encounter an error while reading.

Inserting an object into the cache will unblock other transactions waiting on this object, streaming the contents to clients as the data is written.

The provided write options must not include request headers, and this will return [ErrInvalidArgument] if they do.

Parameters

opts: WriteOptions

Returns

InsertAndStreamBack

View source
func (t *Transaction) InsertAndStreamBack(opts WriteOptions) (WriteCloseAbandoner, *Found, error)

InsertAndStreamBack creates a WriteCloseAbandoner used for inserting an object into the cache, as well as a new Found that can be used to stream the object back to the caller.

Inserting an object into the cache will unblock other transactions waiting on this object, streaming the contents to clients as the data is written.

The returned Found allows the client inserting a cache object to efficiently read back the contents of that item, avoiding the need to buffer contents for copying to multiple destinations. This pattern is commonly required when caching an item that also must be provided to, for example, the client response.

The provided write options must not include request headers, and this will return [ErrInvalidArgument] if they do.

Parameters

opts: WriteOptions

Returns

MustInsert

View source
func (t *Transaction) MustInsert() bool

MustInsert returns true if a usable cached item was not found, and this transaction client is expected to insert one.

This function will return false if any cached item was found, even if stale. Use Transaction.MustInsertOrUpdate instead to handle stale items.

Use Transaction.Insert to insert the object, or Transaction.Cancel to exit the transaction without providing an object.

Returns

bool

MustInsertOrUpdate

View source
func (t *Transaction) MustInsertOrUpdate() bool

MustInsertOrUpdate returns true if a fresh cached item was not found, and this transaction client is expected to insert a new item or update a stale item.

A fresh cached item not being found could mean one of two things:

  • No cached item was found, or
  • A stale cached item was found.

Use Transaction.MustInsert or Transaction.Found to determine whether a new cached item must be inserted.

Use:

Returns

bool
func (t *Transaction) Update(opts WriteOptions) error

Update is used to update a stale object in the cache.

Updating an object freshens it by updating its metadata without changing the object itself.

This method should only be called when Transaction.MustInsertOrUpdate is true and the item is found. Otherwise, an [ErrInvalidOperation] will be returned.

NOTE: Updating a cached item will replace ALL of the configuration in the underlying cache object. If something is not set in the provided WriteOptions, it will revert to the default value. This behavior is likely to change in the future to use the existing configuration. This change will be noted in a future changelog.

The provided write options must not include request headers, and this will return [ErrInvalidArgument] if they do.

This method will return [ErrInvalidOperation] if the object is not stale.

Parameters

opts: WriteOptions

Returns

error