GetOrLoad is utility function gets the provided item from the cache or invokes the provided fetch function. The function also appends and verifies HMAC checksums using provided secret on all cached items to ensure data integrity.
(ctx context.Context, key string, fetch func(output *gather.WriteBuffer) error, output *gather.WriteBuffer)
| 58 | // GetOrLoad is utility function gets the provided item from the cache or invokes the provided fetch function. |
| 59 | // The function also appends and verifies HMAC checksums using provided secret on all cached items to ensure data integrity. |
| 60 | func (c *PersistentCache) GetOrLoad(ctx context.Context, key string, fetch func(output *gather.WriteBuffer) error, output *gather.WriteBuffer) error { |
| 61 | if c == nil { |
| 62 | // special case - also works on non-initialized cache pointer. |
| 63 | return fetch(output) |
| 64 | } |
| 65 | |
| 66 | if c.getFull(ctx, key, output) { |
| 67 | return nil |
| 68 | } |
| 69 | |
| 70 | output.Reset() |
| 71 | |
| 72 | c.exclusiveLock(key) |
| 73 | defer c.exclusiveUnlock(key) |
| 74 | |
| 75 | // check again while holding the mutex |
| 76 | if c.getFull(ctx, key, output) { |
| 77 | return nil |
| 78 | } |
| 79 | |
| 80 | if err := fetch(output); err != nil { |
| 81 | c.reportMissError() |
| 82 | |
| 83 | return err |
| 84 | } |
| 85 | |
| 86 | c.reportMissBytes(int64(output.Length())) |
| 87 | |
| 88 | c.Put(ctx, key, output.Bytes()) |
| 89 | |
| 90 | return nil |
| 91 | } |
| 92 | |
| 93 | // getFull fetches the contents of a full blob. Returns false if not found. |
| 94 | func (c *PersistentCache) getFull(ctx context.Context, key string, output *gather.WriteBuffer) bool { |