go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/logdog/common/storage/storage.go (about)

     1  // Copyright 2015 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  	"context"
    19  	"errors"
    20  
    21  	"go.chromium.org/luci/logdog/common/types"
    22  )
    23  
    24  var (
    25  	// ErrExists returned if an attempt is made to overwrite an existing record.
    26  	ErrExists = errors.New("storage: record exists")
    27  
    28  	// ErrDoesNotExist returned if an attempt is made to read a record that
    29  	// doesn't exist.
    30  	ErrDoesNotExist = errors.New("storage: record does not exist")
    31  
    32  	// ErrBadData is an error returned when the stored data is invalid.
    33  	ErrBadData = errors.New("storage: bad data")
    34  
    35  	// ErrReadOnly can be returned by Storage methods to indicate that the Storage
    36  	// is read-only.
    37  	ErrReadOnly = errors.New("storage: read only")
    38  )
    39  
    40  // PutRequest describes adding a single storage record to BigTable.
    41  type PutRequest struct {
    42  	// Project is the project name of the stream.
    43  	Project string
    44  	// Path is the stream path to retrieve.
    45  	Path types.StreamPath
    46  	// Index is the entry's stream index.
    47  	Index types.MessageIndex
    48  
    49  	// Values are contiguous sequential records to add to the storage. The first
    50  	// index in values corresponds to Index.
    51  	Values [][]byte
    52  }
    53  
    54  // GetRequest is a request to retrieve a series of LogEntry records.
    55  type GetRequest struct {
    56  	// Project is the project name of the stream.
    57  	Project string
    58  	// Path is the stream path to retrieve.
    59  	Path types.StreamPath
    60  	// Index is the entry's stream index.
    61  	Index types.MessageIndex
    62  
    63  	// Limit is the maximum number of records to return before stopping iteration.
    64  	// If <= 0, no maximum limit will be applied.
    65  	//
    66  	// The Storage instance may return fewer records than the supplied Limit as an
    67  	// implementation detail.
    68  	Limit int
    69  	// KeysOnly, if true, allows (but doesn't require) the Storage instance to
    70  	// omit entry data in its get callback. For scanning operations, this can be
    71  	// much cheaper/faster than full data queries.
    72  	KeysOnly bool
    73  }
    74  
    75  // GetCallback is invoked for each record in the Get request. If it returns
    76  // false, iteration should stop.
    77  //
    78  // The MessageIndex may be -1 if the message index isn't known. In this case,
    79  // the caller will have to unmarshal the log entry data to determine its index.
    80  type GetCallback func(*Entry) bool
    81  
    82  // ExpungeRequest is a request to expunge the data associated with this stream.
    83  type ExpungeRequest struct {
    84  	// Project is the project name of the stream.
    85  	Project string
    86  	// Path is the stream path to remove from storage.
    87  	Path types.StreamPath
    88  }
    89  
    90  // Storage is an abstract LogDog storage implementation. Interfaces implementing
    91  // this may be used to store and retrieve log records by the collection service
    92  // layer.
    93  //
    94  // All of these methods must be synchronous and goroutine-safe.
    95  //
    96  // All methods may return errors.Transient errors if they encounter an error
    97  // that may be transient.
    98  type Storage interface {
    99  	// Close shuts down this instance, releasing any allocated resources.
   100  	Close()
   101  
   102  	// Writes log record data to storage.
   103  	//
   104  	// If the data already exists, ErrExists will be returned.
   105  	Put(context.Context, PutRequest) error
   106  
   107  	// Get invokes a callback over a range of sequential LogEntry records.
   108  	//
   109  	// These log entries will be returned in order (e.g., seq(Rn) < seq(Rn+1)),
   110  	// but, depending on ingest, may not be contiguous.
   111  	//
   112  	// The underlying Storage implementation may return fewer records than
   113  	// requested based on availability or implementation details; consequently,
   114  	// receiving fewer than requested records does not necessarily mean that more
   115  	// records are not available.
   116  	//
   117  	// Returns nil if retrieval executed successfully, ErrDoesNotExist if
   118  	// the requested stream does not exist, and an error if an error occurred
   119  	// during retrieval.
   120  	Get(context.Context, GetRequest, GetCallback) error
   121  
   122  	// Expunge removes all entries related to the given project/path.
   123  	Expunge(context.Context, ExpungeRequest) error
   124  
   125  	// Tail retrieves the latest log in the stream. If the stream has no logs, it
   126  	// will fail with ErrDoesNotExist.
   127  	//
   128  	// The MessageIndex may be -1 if the message index isn't known. In this case,
   129  	// the caller will have to unmarshal the log entry data to determine its
   130  	// index.
   131  	Tail(ctx context.Context, projectName string, stream types.StreamPath) (*Entry, error)
   132  }