blob: 47d362d764f364bd5b18f7c4ea3d071e4a5c6fc3 [file] [log] [blame]
// This package supplies a Firestore backed implementation of
// ingestion.IngestionStore. See FIRESTORE.md for more.
package fs_ingestionstore
import (
"time"
"cloud.google.com/go/firestore"
ifirestore "go.skia.org/infra/go/firestore"
"go.skia.org/infra/go/ingestion"
"go.skia.org/infra/go/skerr"
)
const (
// These are the collections in Firestore.
ingestionCollection = "ingestionstore_entries"
// These are the fields we query by
fileHashField = "filehash"
maxAttempts = 10
maxDuration = time.Minute
separator = "|"
)
// Store implements the IngestionStore interface backed by Firestore.
type Store struct {
client *ifirestore.Client
}
// ingestedEntry is the primary document type that keeps track if a
// file with the given md5 hash has been ingested
type ingestedEntry struct {
FileHash string `firestore:"filehash"`
}
// combine creates a key for a file/md5 combination.
func combine(fileName, md5 string) string {
return fileName + separator + md5
}
func New(client *ifirestore.Client) *Store {
return &Store{
client: client,
}
}
// SetResultFileHash fulfills the IngestionStore interface
func (s *Store) SetResultFileHash(fileName, md5 string) error {
ir := s.client.Collection(ingestionCollection).NewDoc()
record := ingestedEntry{
FileHash: combine(fileName, md5),
}
_, err := s.client.Set(ir, record, maxAttempts, maxDuration)
if err != nil {
return skerr.Fmt("could not write %s:%s to ingeststore: %s", fileName, md5, err)
}
return nil
}
// ContainsResultFileHash fulfills the IngestionStore interface
func (s *Store) ContainsResultFileHash(fileName, md5 string) (bool, error) {
q := s.client.Collection(ingestionCollection).Where(fileHashField, "==", combine(fileName, md5)).Limit(1)
found := false
err := s.client.IterDocs("contains", fileName+"|"+md5, q, maxAttempts, maxDuration, func(doc *firestore.DocumentSnapshot) error {
if doc != nil {
found = true
}
return nil
})
if err != nil {
return false, skerr.Fmt("could not locate %s:%s in firestore: %s", fileName, md5, err)
}
return found, nil
}
// Make sure Store fulfills IngestionStore
var _ ingestion.IngestionStore = (*Store)(nil)