@@ -140,6 +140,93 @@ type NotifyArchiver interface {
140
140
fn.EventPublisher [Blob , []* Locator ]
141
141
}
142
142
143
+ // MultiArchiveNotifier is a NotifyArchiver that wraps several other archives
144
+ // and notifies subscribers about new proofs that are added to any of the
145
+ // archives.
146
+ type MultiArchiveNotifier struct {
147
+ archives []NotifyArchiver
148
+ }
149
+
150
+ // NewMultiArchiveNotifier creates a new MultiArchiveNotifier based on the set
151
+ // of specified backends.
152
+ func NewMultiArchiveNotifier (archives ... NotifyArchiver ) * MultiArchiveNotifier {
153
+ return & MultiArchiveNotifier {
154
+ archives : archives ,
155
+ }
156
+ }
157
+
158
+ // FetchProof fetches a proof for an asset uniquely identified by the passed
159
+ // Identifier. The returned proof can either be a full proof file or just a
160
+ // single proof.
161
+ //
162
+ // If a proof cannot be found, then ErrProofNotFound should be returned.
163
+ //
164
+ // NOTE: This is part of the NotifyArchiver interface.
165
+ func (m * MultiArchiveNotifier ) FetchProof (ctx context.Context ,
166
+ id Locator ) (Blob , error ) {
167
+
168
+ for idx := range m .archives {
169
+ a := m .archives [idx ]
170
+
171
+ proofBlob , err := a .FetchProof (ctx , id )
172
+ if errors .Is (err , ErrProofNotFound ) {
173
+ // Try the next archive.
174
+ continue
175
+ } else if err != nil {
176
+ return nil , fmt .Errorf ("error fetching proof " +
177
+ "from archive: %w" , err )
178
+ }
179
+
180
+ return proofBlob , nil
181
+ }
182
+
183
+ return nil , ErrProofNotFound
184
+ }
185
+
186
+ // RegisterSubscriber adds a new subscriber for receiving events. The
187
+ // registration request is forwarded to all registered archives.
188
+ func (m * MultiArchiveNotifier ) RegisterSubscriber (
189
+ receiver * fn.EventReceiver [Blob ], deliverExisting bool ,
190
+ deliverFrom []* Locator ) error {
191
+
192
+ for idx := range m .archives {
193
+ a := m .archives [idx ]
194
+
195
+ err := a .RegisterSubscriber (
196
+ receiver , deliverExisting , deliverFrom ,
197
+ )
198
+ if err != nil {
199
+ return fmt .Errorf ("error registering subscriber: %w" ,
200
+ err )
201
+ }
202
+ }
203
+
204
+ return nil
205
+ }
206
+
207
+ // RemoveSubscriber removes the given subscriber and also stops it from
208
+ // processing events. The removal request is forwarded to all registered
209
+ // archives.
210
+ func (m * MultiArchiveNotifier ) RemoveSubscriber (
211
+ subscriber * fn.EventReceiver [Blob ]) error {
212
+
213
+ for idx := range m .archives {
214
+ a := m .archives [idx ]
215
+
216
+ err := a .RemoveSubscriber (subscriber )
217
+ if err != nil {
218
+ return fmt .Errorf ("error removing subscriber: " +
219
+ "%w" , err )
220
+ }
221
+ }
222
+
223
+ return nil
224
+ }
225
+
226
+ // A compile-time interface to ensure MultiArchiveNotifier meets the
227
+ // NotifyArchiver interface.
228
+ var _ NotifyArchiver = (* MultiArchiveNotifier )(nil )
229
+
143
230
// FileArchiver implements proof Archiver backed by an on-disk file system. The
144
231
// archiver takes a single root directory then creates the following overlap
145
232
// mapping:
0 commit comments