go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/sync/dispatcher/buffer/batch.go (about) 1 // Copyright 2019 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 buffer 16 17 import ( 18 "time" 19 20 "go.chromium.org/luci/common/retry" 21 ) 22 23 // BatchItem is just a container for the user-provided work items. 24 // 25 // This includes the Size of `Data` at the time the work item was added to 26 // the buffer. This will not be modified by Buffer, but can be adjusted 27 // by your application while handling a Batch if your handler needs to trim 28 // this somehow. 29 type BatchItem struct { 30 Item any 31 Size int 32 } 33 34 // Batch represents a collection of individual work items and associated 35 // metadata. 36 // 37 // Batches are are cut by the Channel according to Options.Buffer, and can be 38 // manipulated by ErrorFn and SendFn. 39 // 40 // ErrorFn and SendFn may manipulate the contents of the Batch (Data and Meta) 41 // to do things such as: 42 // - Associate a UID with the Batch (e.g. in the Meta field) to identify it to 43 // remote services for deduplication. 44 // - Remove already-processed items from Data in case the SendFn partially 45 // succeeded. 46 // 47 // The dispatcher accounts for the number of work items in the Batch as it 48 // leases the Batch out; initially the Batch's length will be len(Data). If the 49 // SendFn reduces the length of Data before the NACK, the accounted number of 50 // work items will be accordingly reduced. The accounted length can never grow 51 // (i.e. extending Data doesn't do anything). 52 // 53 // Similarly, if the buffer is configured with BatchSize, the accounted Size of 54 // the batch is defined as the sum of the cached sizes in Data. Reducing this 55 // amount (by removing items, or potentially reducing the Size in a BatchItem) 56 // will reduce the effective Size of this Batch, but adding to Data cannot 57 // increase the Size of the batch. 58 type Batch struct { 59 // Data is the work items pushed into the Buffer, plus their Size as provided 60 // to AddNoBlock. 61 Data []BatchItem 62 63 // Meta is an object which dispatcher.Channel will treat as totally opaque; 64 // You may manipulate it in SendFn or ErrorFn as you see fit. This can be used 65 // for e.g. associating a nonce with the Batch for retries, or stashing 66 // a constructed RPC proto, etc. 67 Meta any 68 69 // id is a 1-based counter which is generated by Buffer when the Batch 70 // is created. Within a Buffer it is monotonically increasing. 71 id uint64 72 73 // retry is the retry.Iterator associated with this Batch. Its Next method 74 // will be called when it is NACK'd. 75 retry retry.Iterator 76 77 // nextSend is the next timestamp after which this Batch is eligible for 78 // sending. 79 // 80 // While the batch is the `currentBatch` in the buffer, this timestamp 81 // represents the deadline for cutting this batch. 82 nextSend time.Time 83 84 // countedItems is the number of items in this Batch as the Buffer counts it. 85 // It starts as the original value of len(Batch.Data) and can decrease if 86 // len(Batch.Data) is smaller on a NACK(). 87 countedItems int 88 89 // countedSize is the number of size units of this Batch as the Buffer counts 90 // it. It starts as the sum of the Size of Data, and can decrease if 91 // BatchItems in Data have their Size reduced or if items are removed 92 // from BatchItems. 93 countedSize int 94 } 95 96 func (b *Batch) canAccept(o *Options, itemSize int) bool { 97 switch { 98 case b == nil: 99 return false 100 case o.BatchItemsMax > -1 && b.countedItems+1 > o.BatchItemsMax: 101 return false 102 case o.BatchSizeMax > -1 && b.countedSize+itemSize > o.BatchSizeMax: 103 return false 104 } 105 return true 106 }