operations.go

 1package entity
 2
 3import (
 4	"time"
 5
 6	"github.com/MichaelMure/git-bug/entities/identity"
 7	"github.com/MichaelMure/git-bug/repository"
 8)
 9
10// OperationType is an operation type identifier
11type OperationType int
12
13// Operation is a piece of data defining a change to reflect on the state of an Entity.
14// What this Operation or Entity's state looks like is not of the resort of this package as it only deals with the
15// data structure and storage.
16type Operation interface {
17	// Id return the Operation identifier
18	//
19	// Some care need to be taken to define a correct Id derivation and enough entropy in the data used to avoid
20	// collisions. Notably:
21	// - the Id of the first Operation will be used as the Id of the Entity. Collision need to be avoided across entities
22	//   of the same type (example: no collision within the "bug" namespace).
23	// - collisions can also happen within the set of Operations of an Entity. Simple Operation might not have enough
24	//   entropy to yield unique Ids (example: two "close" operation within the same second, same author).
25	//   If this is a concern, it is recommended to include a piece of random data in the operation's data, to guarantee
26	//   a minimal amount of entropy and avoid collision.
27	//
28	//   Author's note: I tried to find a clever way around that inelegance (stuffing random useless data into the stored
29	//   structure is not exactly elegant), but I failed to find a proper way. Essentially, anything that would reuse some
30	//   other data (parent operation's Id, lamport clock) or the graph structure (depth) impose that the Id would only
31	//   make sense in the context of the graph and yield some deep coupling between Entity and Operation. This in turn
32	//   make the whole thing even less elegant.
33	//
34	// A common way to derive an Id will be to use the entity.DeriveId() function on the serialized operation data.
35	Id() Id
36	// Type return the type of the operation
37	Type() OperationType
38	// Validate check if the Operation data is valid
39	Validate() error
40	// Author returns the author of this operation
41	Author() identity.Interface
42	// Time return the time when the operation was added
43	Time() time.Time
44
45	// SetMetadata store arbitrary metadata about the operation
46	SetMetadata(key string, value string)
47	// GetMetadata retrieve arbitrary metadata about the operation
48	GetMetadata(key string) (string, bool)
49	// AllMetadata return all metadata for this operation
50	AllMetadata() map[string]string
51}
52
53type OperationWithApply[OpT Operation, SnapT Snapshot] interface {
54	Operation
55
56	// Apply the operation to a Snapshot to create the final state
57	Apply(snapshot SnapT)
58}
59
60// OperationWithFiles is an optional extension for an Operation that has files dependency, stored in git.
61type OperationWithFiles interface {
62	Operation
63
64	// GetFiles return the files needed by this operation
65	// This implies that the Operation maintain and store internally the references to those files. This is how
66	// this information is read later, when loading from storage.
67	// For example, an operation that has a text value referencing some files would maintain a mapping (text ref -->
68	// hash).
69	GetFiles() []repository.Hash
70}
71
72// OperationDoesntChangeSnapshot is an interface signaling that the Operation implementing it doesn't change the
73// snapshot, for example a metadata operation that act on other operations.
74type OperationDoesntChangeSnapshot interface {
75	DoesntChangeSnapshot()
76}