aboutsummaryrefslogtreecommitdiff
path: root/object/store/dual/quarantine.go
blob: b73e48fe5092665262082c8c6f7c5a77dc2a3e88 (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package dual

import (
	"errors"
	"fmt"
	"io"

	"lindenii.org/go/furgit/object/id"
	"lindenii.org/go/furgit/object/store"
	"lindenii.org/go/furgit/object/store/mix"
	"lindenii.org/go/furgit/object/typ"
)

// BeginObjectQuarantine begins an object-wise quarantine on the object side.
//
//nolint:ireturn
func (dual *Dual) BeginObjectQuarantine(opts store.ObjectQuarantineOptions) (store.ObjectQuarantine, error) {
	return dual.object.BeginObjectQuarantine(opts) //nolint:wrapcheck
}

// BeginPackQuarantine begins a pack-wise quarantine on the pack side.
//
//nolint:ireturn
func (dual *Dual) BeginPackQuarantine(opts store.PackQuarantineOptions) (store.PackQuarantine, error) {
	return dual.pack.BeginPackQuarantine(opts) //nolint:wrapcheck
}

// BeginCoordinatedQuarantine begins a quarantine spanning both sides.
//
// If the pack side fails to begin,
// the already-begun object side is discarded before returning.
//
//nolint:ireturn
func (dual *Dual) BeginCoordinatedQuarantine(opts store.CoordinatedQuarantineOptions) (store.CoordinatedQuarantine, error) {
	objectQ, err := dual.object.BeginObjectQuarantine(opts.Object)
	if err != nil {
		return nil, fmt.Errorf("object/store/dual: begin object quarantine: %w", err)
	}

	packQ, err := dual.pack.BeginPackQuarantine(opts.Pack)
	if err != nil {
		_ = objectQ.Discard()

		return nil, fmt.Errorf("object/store/dual: begin pack quarantine: %w", err)
	}

	return newCoordinatedQuarantine(objectQ, packQ), nil
}

// coordinatedQuarantine is one coordinated quarantine over both sides.
type coordinatedQuarantine struct {
	objectQ store.ObjectQuarantine
	packQ   store.PackQuarantine
	reader  store.ObjectReader
}

var _ store.CoordinatedQuarantine = (*coordinatedQuarantine)(nil)

func newCoordinatedQuarantine(
	objectQ store.ObjectQuarantine,
	packQ store.PackQuarantine,
) *coordinatedQuarantine {
	return &coordinatedQuarantine{
		objectQ: objectQ,
		packQ:   packQ,
		reader:  mix.New(objectQ, packQ),
	}
}

func (quarantine *coordinatedQuarantine) ReadBytesFull(id id.ObjectID) ([]byte, error) {
	return quarantine.reader.ReadBytesFull(id) //nolint:wrapcheck
}

func (quarantine *coordinatedQuarantine) ReadBytesContent(id id.ObjectID) (typ.Type, []byte, error) {
	return quarantine.reader.ReadBytesContent(id) //nolint:wrapcheck
}

func (quarantine *coordinatedQuarantine) ReadReaderFull(id id.ObjectID) (io.ReadCloser, error) {
	return quarantine.reader.ReadReaderFull(id) //nolint:wrapcheck
}

func (quarantine *coordinatedQuarantine) ReadReaderContent(id id.ObjectID) (typ.Type, int, io.ReadCloser, error) {
	return quarantine.reader.ReadReaderContent(id) //nolint:wrapcheck
}

func (quarantine *coordinatedQuarantine) ReadSize(id id.ObjectID) (int, error) {
	return quarantine.reader.ReadSize(id) //nolint:wrapcheck
}

func (quarantine *coordinatedQuarantine) ReadHeader(id id.ObjectID) (typ.Type, int, error) {
	return quarantine.reader.ReadHeader(id) //nolint:wrapcheck
}

func (quarantine *coordinatedQuarantine) Refresh() error {
	return quarantine.reader.Refresh() //nolint:wrapcheck
}

func (quarantine *coordinatedQuarantine) WriteBytesFull(raw []byte) (id.ObjectID, error) {
	return quarantine.objectQ.WriteBytesFull(raw) //nolint:wrapcheck
}

func (quarantine *coordinatedQuarantine) WriteBytesContent(ty typ.Type, content []byte) (id.ObjectID, error) {
	return quarantine.objectQ.WriteBytesContent(ty, content) //nolint:wrapcheck
}

func (quarantine *coordinatedQuarantine) WriteReaderFull(src io.Reader) (id.ObjectID, error) {
	return quarantine.objectQ.WriteReaderFull(src) //nolint:wrapcheck
}

func (quarantine *coordinatedQuarantine) WriteReaderContent(ty typ.Type, size int, src io.Reader) (id.ObjectID, error) {
	return quarantine.objectQ.WriteReaderContent(ty, size, src) //nolint:wrapcheck
}

func (quarantine *coordinatedQuarantine) WritePack(src io.Reader, opts store.PackWriteOptions) error {
	return quarantine.packQ.WritePack(src, opts) //nolint:wrapcheck
}

// Promote publishes both halves and joins their errors.
func (quarantine *coordinatedQuarantine) Promote() error {
	return errors.Join(quarantine.objectQ.Promote(), quarantine.packQ.Promote())
}

// Discard abandons both halves and joins their errors.
func (quarantine *coordinatedQuarantine) Discard() error {
	return errors.Join(quarantine.objectQ.Discard(), quarantine.packQ.Discard())
}