go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/logdog/common/storage/cache.go (about) 1 // Copyright 2016 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package storage 16 17 import ( 18 "bufio" 19 "context" 20 "crypto/sha256" 21 "encoding/hex" 22 "time" 23 ) 24 25 // CacheKey is a single cache item's key. 26 type CacheKey struct { 27 // Schema is the item's schema value. If empty, the item is schemaless. 28 Schema string 29 30 // Type is the item's type identifier. If empty, the item has no type. 31 Type string 32 33 // Key is the item's individual key. It uniquely identifies the Item within 34 // the scope of the Schema and Type. 35 Key string 36 } 37 38 // Cache is a simple cache interface. It is capable of storage and retrieval. 39 type Cache interface { 40 // Put caches an Items into the cache. If an item already exists in the cache, 41 // it will be overridden. 42 // 43 // The data in val may be directly retained by the cache, and the caller 44 // promises not to mutate it after being passed to Put. 45 // 46 // If exp, the supplied expiration Duration, is >0, the cache should only 47 // store the data if it can expire it after this period of time. 48 // 49 // This method does not return whether or not the caching storage was 50 // successful. 51 Put(c context.Context, key CacheKey, val []byte, exp time.Duration) 52 53 // Get retrieves a cached entry. If the entry was present, the returned 54 // boolean will be true. 55 // 56 // The returned byte slice may not be modified by the caller. 57 // 58 // This method does not distinguish between an error and missing data. Either 59 // valid data is returned, or it is not. 60 Get(c context.Context, key CacheKey) ([]byte, bool) 61 } 62 63 // HashKey composes a hex-encoded SHA256 string from the supplied parts. The 64 // local schema version and KeyType are included in the hash. 65 func HashKey(parts ...string) string { 66 hash := sha256.New() 67 bio := bufio.NewWriter(hash) 68 69 // Add a full NULL-delimited key sequence segment to our hash. 70 for i, part := range parts { 71 // Write the separator, except for the first key. 72 if i > 0 { 73 if _, err := bio.WriteRune('\x00'); err != nil { 74 panic(err) 75 } 76 } 77 78 if _, err := bio.WriteString(part); err != nil { 79 panic(err) 80 } 81 } 82 if err := bio.Flush(); err != nil { 83 panic(err) 84 } 85 86 // Return the hex-encoded hash sum. 87 return hex.EncodeToString(hash.Sum(nil)) 88 }