github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/nomad/state/paginator/tokenizer.go (about) 1 package paginator 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // Tokenizer is the interface that must be implemented to provide pagination 9 // tokens to the Paginator. 10 type Tokenizer interface { 11 // GetToken returns the pagination token for the given element. 12 GetToken(interface{}) string 13 } 14 15 // IDGetter is the interface that must be implemented by structs that need to 16 // have their ID as part of the pagination token. 17 type IDGetter interface { 18 GetID() string 19 } 20 21 // NamespaceGetter is the interface that must be implemented by structs that 22 // need to have their Namespace as part of the pagination token. 23 type NamespaceGetter interface { 24 GetNamespace() string 25 } 26 27 // CreateIndexGetter is the interface that must be implemented by structs that 28 // need to have their CreateIndex as part of the pagination token. 29 type CreateIndexGetter interface { 30 GetCreateIndex() uint64 31 } 32 33 // StructsTokenizerOptions is the configuration provided to a StructsTokenizer. 34 // 35 // These are some of the common use cases: 36 // 37 // Structs that can be uniquely identified with only its own ID: 38 // 39 // StructsTokenizerOptions { 40 // WithID: true, 41 // } 42 // 43 // Structs that are only unique within their namespace: 44 // 45 // StructsTokenizerOptions { 46 // WithID: true, 47 // WithNamespace: true, 48 // } 49 // 50 // Structs that can be sorted by their create index should also set 51 // `WithCreateIndex` to `true` along with the other options: 52 // 53 // StructsTokenizerOptions { 54 // WithID: true, 55 // WithNamespace: true, 56 // WithCreateIndex: true, 57 // } 58 type StructsTokenizerOptions struct { 59 WithCreateIndex bool 60 WithNamespace bool 61 WithID bool 62 } 63 64 // StructsTokenizer is an pagination token generator that can create different 65 // formats of pagination tokens based on common fields found in the structs 66 // package. 67 type StructsTokenizer struct { 68 opts StructsTokenizerOptions 69 } 70 71 // NewStructsTokenizer returns a new StructsTokenizer. 72 func NewStructsTokenizer(_ Iterator, opts StructsTokenizerOptions) StructsTokenizer { 73 return StructsTokenizer{ 74 opts: opts, 75 } 76 } 77 78 func (it StructsTokenizer) GetToken(raw interface{}) string { 79 if raw == nil { 80 return "" 81 } 82 83 parts := []string{} 84 85 if it.opts.WithCreateIndex { 86 token := raw.(CreateIndexGetter).GetCreateIndex() 87 parts = append(parts, fmt.Sprintf("%v", token)) 88 } 89 90 if it.opts.WithNamespace { 91 token := raw.(NamespaceGetter).GetNamespace() 92 parts = append(parts, token) 93 } 94 95 if it.opts.WithID { 96 token := raw.(IDGetter).GetID() 97 parts = append(parts, token) 98 } 99 100 // Use a character that is not part of validNamespaceName as separator to 101 // avoid accidentally generating collisions. 102 // For example, namespace `a` and job `b-c` would collide with namespace 103 // `a-b` and job `c` into the same token `a-b-c`, since `-` is an allowed 104 // character in namespace. 105 return strings.Join(parts, ".") 106 }