+209
bus/firehose/handler.go
+209
bus/firehose/handler.go
···
1
+
package kafkafirehose
2
+
3
+
import (
4
+
"bytes"
5
+
"context"
6
+
"encoding/json"
7
+
"fmt"
8
+
"strings"
9
+
"time"
10
+
11
+
"github.com/bluesky-social/indigo/atproto/atdata"
12
+
"github.com/bluesky-social/indigo/events"
13
+
"github.com/bluesky-social/indigo/repo"
14
+
"github.com/twmb/franz-go/pkg/kgo"
15
+
vyletkafka "github.com/vylet-app/go/bus/proto"
16
+
"google.golang.org/protobuf/types/known/timestamppb"
17
+
)
18
+
19
+
func (kf *KafkaFirehose) handleEvent(ctx context.Context, evt *events.XRPCStreamEvent) error {
20
+
logger := kf.logger.With("name", "handleEvent", "seq", evt.Sequence())
21
+
logger.Debug("received event")
22
+
23
+
var kind string
24
+
if evt.RepoIdentity != nil {
25
+
kind = "identity"
26
+
} else if evt.RepoAccount != nil {
27
+
kind = "account"
28
+
} else if evt.RepoCommit != nil {
29
+
kind = "commit"
30
+
} else if evt.RepoInfo != nil {
31
+
kind = "info"
32
+
} else if evt.RepoSync != nil {
33
+
kind = "sync"
34
+
} else {
35
+
kind = "unknown"
36
+
}
37
+
38
+
eventsReceived.WithLabelValues(kind).Inc()
39
+
40
+
if evt.RepoCommit == nil && evt.RepoIdentity == nil && evt.RepoAccount == nil {
41
+
logger.Debug("not a handled operation, skipping")
42
+
return nil
43
+
}
44
+
45
+
kf.setCursor(evt.Sequence())
46
+
47
+
var kafkaEvts []*vyletkafka.FirehoseEvent
48
+
49
+
if evt.RepoIdentity != nil {
50
+
b, err := json.Marshal(evt.RepoIdentity)
51
+
if err != nil {
52
+
return fmt.Errorf("failed to marshal identity event into bytes: %w", err)
53
+
}
54
+
55
+
parsedTime, err := time.Parse(time.RFC3339Nano, evt.RepoIdentity.Time)
56
+
if err != nil {
57
+
return fmt.Errorf("failed to marshal identity event time %s to go time: %w", evt.RepoIdentity.Time, err)
58
+
}
59
+
60
+
kafkaEvts = append(kafkaEvts, &vyletkafka.FirehoseEvent{
61
+
Did: evt.RepoIdentity.Did,
62
+
Timestamp: timestamppb.New(parsedTime),
63
+
Identity: b,
64
+
})
65
+
} else if evt.RepoAccount != nil {
66
+
b, err := json.Marshal(evt.RepoAccount)
67
+
if err != nil {
68
+
return fmt.Errorf("failed to marshal account event into bytes: %w", err)
69
+
}
70
+
71
+
parsedTime, err := time.Parse(time.RFC3339Nano, evt.RepoAccount.Time)
72
+
if err != nil {
73
+
return fmt.Errorf("failed to marshal account event time %s to go time: %w", evt.RepoAccount.Time, err)
74
+
}
75
+
76
+
kafkaEvts = append(kafkaEvts, &vyletkafka.FirehoseEvent{
77
+
Did: evt.RepoAccount.Did,
78
+
Timestamp: timestamppb.New(parsedTime),
79
+
Account: b,
80
+
})
81
+
} else {
82
+
rr, err := repo.ReadRepoFromCar(ctx, bytes.NewReader(evt.RepoCommit.Blocks))
83
+
if err != nil {
84
+
logger.Error("failed to read repo from car", "did", evt.RepoCommit.Repo, "err", err)
85
+
return nil
86
+
}
87
+
88
+
parsedTime, err := time.Parse(time.RFC3339Nano, evt.RepoCommit.Time)
89
+
if err != nil {
90
+
return fmt.Errorf("failed to marshal commit event time %s to go time: %w", evt.RepoCommit.Time, err)
91
+
}
92
+
93
+
protoTime := timestamppb.New(parsedTime)
94
+
95
+
for _, op := range evt.RepoCommit.Ops {
96
+
func() {
97
+
status := "error"
98
+
var collection string
99
+
100
+
defer func() {
101
+
recordsHandled.WithLabelValues(status, collection).Inc()
102
+
}()
103
+
104
+
pts := strings.Split(op.Path, "/")
105
+
if len(pts) != 2 {
106
+
logger.Error("failed to parse path, lenght of parts is not two", "path", op.Path)
107
+
return
108
+
}
109
+
110
+
collection = pts[0]
111
+
rkey := pts[1]
112
+
113
+
wantsCollection := false
114
+
for _, desiredCollection := range kf.desiredCollections {
115
+
if collection == desiredCollection || strings.HasPrefix(collection, desiredCollection) {
116
+
wantsCollection = true
117
+
break
118
+
}
119
+
}
120
+
if !wantsCollection {
121
+
logger.Debug("collection undesired, skipping", "collection", collection)
122
+
status = "skipped"
123
+
return
124
+
}
125
+
126
+
var operation vyletkafka.CommitOperation
127
+
128
+
switch op.Action {
129
+
case "create":
130
+
operation = vyletkafka.CommitOperation_COMMIT_OPERATION_CREATE
131
+
case "update":
132
+
operation = vyletkafka.CommitOperation_COMMIT_OPERATION_UPDATE
133
+
case "delete":
134
+
operation = vyletkafka.CommitOperation_COMMIT_OPERATION_DELETE
135
+
}
136
+
137
+
var rec map[string]any
138
+
var recCid string
139
+
140
+
if op.Action == "create" || op.Action == "update" {
141
+
rcid, recB, err := rr.GetRecordBytes(ctx, op.Path)
142
+
if err != nil {
143
+
logger.Error("failed to read record bytes", "err", err)
144
+
return
145
+
}
146
+
147
+
recCid = rcid.String()
148
+
if recCid != op.Cid.String() {
149
+
logger.Error("record cid mismatch", "expected", *op.Cid, "actual", recCid)
150
+
return
151
+
}
152
+
153
+
maybeRec, err := atdata.UnmarshalCBOR(*recB)
154
+
if err != nil {
155
+
logger.Error("failed to unmarshal record", "err", err)
156
+
}
157
+
rec = maybeRec
158
+
}
159
+
160
+
var b []byte
161
+
if rec != nil {
162
+
maybeB, err := json.Marshal(rec)
163
+
if err != nil {
164
+
logger.Error("failed to marshal record map to json", "err", err)
165
+
return
166
+
}
167
+
b = maybeB
168
+
}
169
+
170
+
kafkaEvts = append(kafkaEvts,
171
+
&vyletkafka.FirehoseEvent{
172
+
Did: evt.RepoCommit.Repo,
173
+
Timestamp: protoTime,
174
+
Commit: &vyletkafka.Commit{
175
+
Rev: evt.RepoCommit.Rev,
176
+
Operation: operation,
177
+
Collection: collection,
178
+
Rkey: rkey,
179
+
Record: b,
180
+
Cid: recCid,
181
+
},
182
+
})
183
+
184
+
status = "ok"
185
+
}()
186
+
}
187
+
}
188
+
189
+
for _, kafkaEvt := range kafkaEvts {
190
+
if err := kf.producer.ProduceAsync(ctx, kafkaEvt.Did, kafkaEvt, func(r *kgo.Record, err error) {
191
+
status := "error"
192
+
defer func() {
193
+
messagesProduced.WithLabelValues(status).Inc()
194
+
}()
195
+
196
+
if err != nil {
197
+
logger.Error("error after producting event async", "err", err)
198
+
return
199
+
}
200
+
201
+
status = "ok"
202
+
logger.Debug("produced event")
203
+
}); err != nil {
204
+
logger.Error("failed to produce event async", "err", err)
205
+
}
206
+
}
207
+
208
+
return nil
209
+
}
+27
bus/firehose/metrics.go
+27
bus/firehose/metrics.go
···
1
+
package kafkafirehose
2
+
3
+
import (
4
+
"github.com/prometheus/client_golang/prometheus"
5
+
"github.com/prometheus/client_golang/prometheus/promauto"
6
+
)
7
+
8
+
const (
9
+
namespace = "kafkafirehose"
10
+
)
11
+
12
+
var (
13
+
eventsReceived = promauto.NewCounterVec(prometheus.CounterOpts{
14
+
Namespace: namespace,
15
+
Name: "events_received",
16
+
}, []string{"kind"})
17
+
18
+
recordsHandled = promauto.NewCounterVec(prometheus.CounterOpts{
19
+
Namespace: namespace,
20
+
Name: "records_handled",
21
+
}, []string{"status", "collection"})
22
+
23
+
messagesProduced = promauto.NewCounterVec(prometheus.CounterOpts{
24
+
Namespace: namespace,
25
+
Name: "messages_produced",
26
+
}, []string{"status"})
27
+
)
+251
-2
bus/firehose/server.go
+251
-2
bus/firehose/server.go
···
1
1
package kafkafirehose
2
2
3
+
import (
4
+
"context"
5
+
"fmt"
6
+
"log/slog"
7
+
"net/http"
8
+
"net/url"
9
+
"os"
10
+
"os/signal"
11
+
"strings"
12
+
"sync"
13
+
"syscall"
14
+
"time"
15
+
16
+
"github.com/bluesky-social/go-util/pkg/bus/cursor"
17
+
"github.com/bluesky-social/go-util/pkg/bus/producer"
18
+
"github.com/bluesky-social/indigo/events"
19
+
"github.com/bluesky-social/indigo/events/schedulers/parallel"
20
+
"github.com/gorilla/websocket"
21
+
vyletkafka "github.com/vylet-app/go/bus/proto"
22
+
)
23
+
3
24
type KafkaFirehose struct {
25
+
logger *slog.Logger
26
+
27
+
producer *producer.Producer[*vyletkafka.FirehoseEvent]
28
+
29
+
cursor *cursor.Cursor[*vyletkafka.SequenceCursor]
30
+
lastCursor *int64
31
+
cursorLk sync.Mutex
32
+
saveLastCursor chan struct{}
33
+
lastCursorSaved chan struct{}
34
+
35
+
desiredCollections []string
36
+
websocketHost string
4
37
}
5
38
6
39
type Args struct {
40
+
Logger *slog.Logger
41
+
42
+
DesiredCollections []string
43
+
WebsocketHost string
44
+
BootstrapServers []string
45
+
OutputTopic string
7
46
}
8
47
9
-
func New(args *Args) (*KafkaFirehose, error) {
10
-
kf := KafkaFirehose{}
48
+
func New(ctx context.Context, args *Args) (*KafkaFirehose, error) {
49
+
if args.Logger == nil {
50
+
args.Logger = slog.Default()
51
+
}
52
+
53
+
logger := args.Logger
54
+
55
+
busProducer, err := producer.New(
56
+
ctx,
57
+
logger.With("component", "producer"),
58
+
args.BootstrapServers,
59
+
args.OutputTopic,
60
+
producer.WithEnsureTopic[*vyletkafka.FirehoseEvent](true),
61
+
producer.WithTopicPartitions[*vyletkafka.FirehoseEvent](24),
62
+
producer.WithRetentionTime[*vyletkafka.FirehoseEvent](24*time.Hour),
63
+
producer.WithReplicationFactor[*vyletkafka.FirehoseEvent](1),
64
+
)
65
+
if err != nil {
66
+
return nil, fmt.Errorf("failed to create kafka producer: %w", err)
67
+
}
68
+
69
+
cursorProducer, err := cursor.New[*vyletkafka.SequenceCursor](ctx, args.BootstrapServers, args.OutputTopic+"-cursor")
70
+
if err != nil {
71
+
return nil, fmt.Errorf("failed to create cursor producer: %w", err)
72
+
}
73
+
74
+
desiredCollections := make([]string, len(args.DesiredCollections))
75
+
for idx, coll := range args.DesiredCollections {
76
+
desiredCollections[idx] = strings.TrimSuffix(strings.TrimSuffix(coll, ".*"), ".")
77
+
}
78
+
79
+
kf := KafkaFirehose{
80
+
logger: args.Logger,
81
+
82
+
producer: busProducer,
83
+
84
+
cursor: cursorProducer,
85
+
saveLastCursor: make(chan struct{}, 1),
86
+
lastCursorSaved: make(chan struct{}, 1),
87
+
88
+
desiredCollections: desiredCollections,
89
+
websocketHost: args.WebsocketHost,
90
+
}
91
+
92
+
logger.Info("attempting to fetch last cursor from bus")
93
+
if err := kf.loadCursor(ctx); err != nil {
94
+
return nil, fmt.Errorf("failed to fetch or init cursor: %w", err)
95
+
}
11
96
12
97
return &kf, nil
13
98
}
99
+
100
+
func (kf *KafkaFirehose) Run(ctx context.Context) error {
101
+
logger := kf.logger.With("name", "Run")
102
+
103
+
wsDialer := websocket.DefaultDialer
104
+
u, err := url.Parse(kf.websocketHost)
105
+
if err != nil {
106
+
return fmt.Errorf("failed to parse websocket host: %w", err)
107
+
}
108
+
109
+
u.Path = "/xrpc/com.atproto.sync.subscribeRepos"
110
+
111
+
cursor := kf.getCursor()
112
+
if cursor != nil {
113
+
u.RawQuery = fmt.Sprintf("cursor=%d", *cursor)
114
+
}
115
+
116
+
// run the consumer in a goroutine and
117
+
shutdownConsumer := make(chan struct{}, 1)
118
+
consumerShutdown := make(chan struct{}, 1)
119
+
120
+
go func() {
121
+
logger := kf.logger.With("component", "consumer")
122
+
123
+
logger.Info("subscribing to repo event stream", "url", u.String())
124
+
125
+
// dial the websocket
126
+
conn, _, err := wsDialer.Dial(u.String(), http.Header{
127
+
"User-Agent": []string{"vylet-kafka/0.0.0"},
128
+
})
129
+
if err != nil {
130
+
logger.Error("error dialing websocket", "err", err)
131
+
close(shutdownConsumer)
132
+
return
133
+
}
134
+
135
+
// setup a new event scheduler
136
+
parallelism := 400
137
+
138
+
scheduler := parallel.NewScheduler(parallelism, 1000, kf.websocketHost, kf.handleEvent)
139
+
140
+
// run the consumer and wait for it to be shut down
141
+
go func() {
142
+
if err := events.HandleRepoStream(ctx, conn, scheduler, logger); err != nil {
143
+
logger.Error("error handling repo stream", "err", err)
144
+
}
145
+
}()
146
+
147
+
<-shutdownConsumer
148
+
149
+
if err := conn.Close(); err != nil {
150
+
logger.Error("error closing websocket", "err", err)
151
+
} else {
152
+
logger.Info("websocket closed")
153
+
}
154
+
155
+
close(consumerShutdown)
156
+
}()
157
+
158
+
go kf.periodicallySaveCursor(ctx)
159
+
160
+
signals := make(chan os.Signal, 1)
161
+
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
162
+
163
+
// wait for any of the following to arise
164
+
select {
165
+
case sig := <-signals:
166
+
logger.Info("received exit signal", "signal", sig)
167
+
close(shutdownConsumer)
168
+
case <-ctx.Done():
169
+
logger.Info("main context cancelled")
170
+
close(shutdownConsumer)
171
+
case <-consumerShutdown:
172
+
logger.Warn("consumer shutdown unexpectedly, forcing exit")
173
+
}
174
+
175
+
select {
176
+
case <-consumerShutdown:
177
+
case <-time.After(5 * time.Second):
178
+
logger.Warn("websocket did not shut down within five seconds, forcefully shutting down")
179
+
}
180
+
181
+
// close the producer
182
+
kf.producer.Close()
183
+
if err := kf.cursor.Close(); err != nil {
184
+
logger.Error("error closing cursor", "err", err)
185
+
}
186
+
187
+
logger.Info("kafka firehose shutdown successfully")
188
+
189
+
return nil
190
+
}
191
+
192
+
func isFinalCursor(c *vyletkafka.SequenceCursor) bool {
193
+
return c != nil && c.SavedOnExit
194
+
}
195
+
196
+
func (kf *KafkaFirehose) loadCursor(ctx context.Context) error {
197
+
kf.cursorLk.Lock()
198
+
defer kf.cursorLk.Unlock()
199
+
200
+
if c, err := kf.cursor.Load(ctx, isFinalCursor); err != nil {
201
+
return fmt.Errorf("failed to load cursor: %w", err)
202
+
} else if c != nil {
203
+
kf.lastCursor = &c.Sequence
204
+
kf.logger.Info("loaded last cursor", "cursor", kf.lastCursor)
205
+
} else {
206
+
kf.logger.Info("no previous cursor found, starting fresh")
207
+
}
208
+
209
+
return nil
210
+
}
211
+
212
+
func (kf *KafkaFirehose) getCursor() *int64 {
213
+
kf.cursorLk.Lock()
214
+
defer kf.cursorLk.Unlock()
215
+
216
+
return kf.lastCursor
217
+
}
218
+
219
+
func (kf *KafkaFirehose) setCursor(c int64) {
220
+
kf.cursorLk.Lock()
221
+
defer kf.cursorLk.Unlock()
222
+
kf.lastCursor = &c
223
+
}
224
+
225
+
func (kf *KafkaFirehose) periodicallySaveCursor(ctx context.Context) {
226
+
ticker := time.NewTicker(5 * time.Second)
227
+
defer ticker.Stop()
228
+
229
+
defer func() {
230
+
kf.cursorLk.Lock()
231
+
defer kf.cursorLk.Unlock()
232
+
if kf.lastCursor != nil {
233
+
finalCursor := vyletkafka.SequenceCursor{Sequence: *kf.lastCursor, SavedOnExit: true}
234
+
if err := kf.cursor.Save(context.Background(), &finalCursor); err != nil {
235
+
kf.logger.Error("failed to save final cursor", "err", err)
236
+
} else {
237
+
kf.logger.Info("saved final cursor on exit", "cursor", *kf.lastCursor)
238
+
}
239
+
}
240
+
close(kf.lastCursorSaved)
241
+
}()
242
+
243
+
for {
244
+
select {
245
+
case <-kf.saveLastCursor:
246
+
kf.logger.Info("saving last cursor...")
247
+
return
248
+
case <-ticker.C:
249
+
kf.cursorLk.Lock()
250
+
last := kf.lastCursor
251
+
kf.cursorLk.Unlock()
252
+
253
+
if last != nil {
254
+
if err := kf.cursor.Save(ctx, &vyletkafka.SequenceCursor{Sequence: *last}); err != nil {
255
+
kf.logger.Info("failed to save cursor", "err", err)
256
+
} else {
257
+
kf.logger.Info("saved cursor", "sequence", *last)
258
+
}
259
+
}
260
+
}
261
+
}
262
+
}
+15
bus/proto/buf.gen.yaml
+15
bus/proto/buf.gen.yaml
···
1
+
version: v2
2
+
managed:
3
+
enabled: true
4
+
override:
5
+
- file_option: go_package_prefix
6
+
module: buf.build/bufbuild/confluent
7
+
value: buf.build/gen/go/bufbuild/confluent/protocolbuffers/go
8
+
disable:
9
+
- file_option: go_package
10
+
module: buf.build/bufbuild/protovalidate
11
+
plugins:
12
+
- remote: buf.build/protocolbuffers/go:v1.36.6
13
+
out: .
14
+
opt: paths=source_relative
15
+
+9
bus/proto/buf.lock
+9
bus/proto/buf.lock
···
1
+
# Generated by buf. DO NOT EDIT.
2
+
version: v2
3
+
deps:
4
+
- name: buf.build/bufbuild/confluent
5
+
commit: 65369e65bbcd4715989b6fbe53cb8a71
6
+
digest: b5:4c002e10c90c1b84be15e7f1f95508ad07499225faf79305f9e03bd7b0dc174e5720b6f3762e30dee4d703cba4c7522c4242b58770c28c2d881c35e86dc114fb
7
+
- name: buf.build/bufbuild/protovalidate
8
+
commit: 52f32327d4b045a79293a6ad4e7e1236
9
+
digest: b5:cbabc98d4b7b7b0447c9b15f68eeb8a7a44ef8516cb386ac5f66e7fd4062cd6723ed3f452ad8c384b851f79e33d26e7f8a94e2b807282b3def1cd966c7eace97
+14
bus/proto/buf.yaml
+14
bus/proto/buf.yaml
···
1
+
# For details on buf.yaml configuration, visit https://buf.build/docs/configuration/v2/buf-yaml
2
+
version: v2
3
+
breaking:
4
+
use:
5
+
- FILE
6
+
lint:
7
+
use:
8
+
- STANDARD
9
+
except:
10
+
- PACKAGE_VERSION_SUFFIX
11
+
- PACKAGE_DIRECTORY_MATCH
12
+
deps:
13
+
- buf.build/bufbuild/confluent
14
+
- buf.build/bufbuild/protovalidate
+384
bus/proto/vylet_kafka.pb.go
+384
bus/proto/vylet_kafka.pb.go
···
1
+
// Code generated by protoc-gen-go. DO NOT EDIT.
2
+
// versions:
3
+
// protoc-gen-go v1.36.6
4
+
// protoc (unknown)
5
+
// source: vylet_kafka.proto
6
+
7
+
package vyletkafka
8
+
9
+
import (
10
+
_ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate"
11
+
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
12
+
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
13
+
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
14
+
reflect "reflect"
15
+
sync "sync"
16
+
unsafe "unsafe"
17
+
)
18
+
19
+
const (
20
+
// Verify that this generated code is sufficiently up-to-date.
21
+
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
22
+
// Verify that runtime/protoimpl is sufficiently up-to-date.
23
+
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
24
+
)
25
+
26
+
type CommitOperation int32
27
+
28
+
const (
29
+
CommitOperation_COMMIT_OPERATION_UNSPECIFIED CommitOperation = 0
30
+
CommitOperation_COMMIT_OPERATION_CREATE CommitOperation = 1
31
+
CommitOperation_COMMIT_OPERATION_UPDATE CommitOperation = 2
32
+
CommitOperation_COMMIT_OPERATION_DELETE CommitOperation = 3
33
+
)
34
+
35
+
// Enum value maps for CommitOperation.
36
+
var (
37
+
CommitOperation_name = map[int32]string{
38
+
0: "COMMIT_OPERATION_UNSPECIFIED",
39
+
1: "COMMIT_OPERATION_CREATE",
40
+
2: "COMMIT_OPERATION_UPDATE",
41
+
3: "COMMIT_OPERATION_DELETE",
42
+
}
43
+
CommitOperation_value = map[string]int32{
44
+
"COMMIT_OPERATION_UNSPECIFIED": 0,
45
+
"COMMIT_OPERATION_CREATE": 1,
46
+
"COMMIT_OPERATION_UPDATE": 2,
47
+
"COMMIT_OPERATION_DELETE": 3,
48
+
}
49
+
)
50
+
51
+
func (x CommitOperation) Enum() *CommitOperation {
52
+
p := new(CommitOperation)
53
+
*p = x
54
+
return p
55
+
}
56
+
57
+
func (x CommitOperation) String() string {
58
+
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
59
+
}
60
+
61
+
func (CommitOperation) Descriptor() protoreflect.EnumDescriptor {
62
+
return file_vylet_kafka_proto_enumTypes[0].Descriptor()
63
+
}
64
+
65
+
func (CommitOperation) Type() protoreflect.EnumType {
66
+
return &file_vylet_kafka_proto_enumTypes[0]
67
+
}
68
+
69
+
func (x CommitOperation) Number() protoreflect.EnumNumber {
70
+
return protoreflect.EnumNumber(x)
71
+
}
72
+
73
+
// Deprecated: Use CommitOperation.Descriptor instead.
74
+
func (CommitOperation) EnumDescriptor() ([]byte, []int) {
75
+
return file_vylet_kafka_proto_rawDescGZIP(), []int{0}
76
+
}
77
+
78
+
type FirehoseEvent struct {
79
+
state protoimpl.MessageState `protogen:"open.v1"`
80
+
Did string `protobuf:"bytes,1,opt,name=did,proto3" json:"did,omitempty"`
81
+
Timestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
82
+
Commit *Commit `protobuf:"bytes,3,opt,name=commit,proto3,oneof" json:"commit,omitempty"`
83
+
Account []byte `protobuf:"bytes,4,opt,name=account,proto3,oneof" json:"account,omitempty"`
84
+
Identity []byte `protobuf:"bytes,5,opt,name=identity,proto3,oneof" json:"identity,omitempty"`
85
+
unknownFields protoimpl.UnknownFields
86
+
sizeCache protoimpl.SizeCache
87
+
}
88
+
89
+
func (x *FirehoseEvent) Reset() {
90
+
*x = FirehoseEvent{}
91
+
mi := &file_vylet_kafka_proto_msgTypes[0]
92
+
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
93
+
ms.StoreMessageInfo(mi)
94
+
}
95
+
96
+
func (x *FirehoseEvent) String() string {
97
+
return protoimpl.X.MessageStringOf(x)
98
+
}
99
+
100
+
func (*FirehoseEvent) ProtoMessage() {}
101
+
102
+
func (x *FirehoseEvent) ProtoReflect() protoreflect.Message {
103
+
mi := &file_vylet_kafka_proto_msgTypes[0]
104
+
if x != nil {
105
+
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
106
+
if ms.LoadMessageInfo() == nil {
107
+
ms.StoreMessageInfo(mi)
108
+
}
109
+
return ms
110
+
}
111
+
return mi.MessageOf(x)
112
+
}
113
+
114
+
// Deprecated: Use FirehoseEvent.ProtoReflect.Descriptor instead.
115
+
func (*FirehoseEvent) Descriptor() ([]byte, []int) {
116
+
return file_vylet_kafka_proto_rawDescGZIP(), []int{0}
117
+
}
118
+
119
+
func (x *FirehoseEvent) GetDid() string {
120
+
if x != nil {
121
+
return x.Did
122
+
}
123
+
return ""
124
+
}
125
+
126
+
func (x *FirehoseEvent) GetTimestamp() *timestamppb.Timestamp {
127
+
if x != nil {
128
+
return x.Timestamp
129
+
}
130
+
return nil
131
+
}
132
+
133
+
func (x *FirehoseEvent) GetCommit() *Commit {
134
+
if x != nil {
135
+
return x.Commit
136
+
}
137
+
return nil
138
+
}
139
+
140
+
func (x *FirehoseEvent) GetAccount() []byte {
141
+
if x != nil {
142
+
return x.Account
143
+
}
144
+
return nil
145
+
}
146
+
147
+
func (x *FirehoseEvent) GetIdentity() []byte {
148
+
if x != nil {
149
+
return x.Identity
150
+
}
151
+
return nil
152
+
}
153
+
154
+
type Commit struct {
155
+
state protoimpl.MessageState `protogen:"open.v1"`
156
+
Rev string `protobuf:"bytes,1,opt,name=rev,proto3" json:"rev,omitempty"`
157
+
Operation CommitOperation `protobuf:"varint,2,opt,name=operation,proto3,enum=vyletkafka.CommitOperation" json:"operation,omitempty"`
158
+
Collection string `protobuf:"bytes,3,opt,name=collection,proto3" json:"collection,omitempty"`
159
+
Rkey string `protobuf:"bytes,4,opt,name=rkey,proto3" json:"rkey,omitempty"`
160
+
Record []byte `protobuf:"bytes,5,opt,name=record,proto3" json:"record,omitempty"` // json.RawMessage as opaque bytes
161
+
Cid string `protobuf:"bytes,6,opt,name=cid,proto3" json:"cid,omitempty"`
162
+
unknownFields protoimpl.UnknownFields
163
+
sizeCache protoimpl.SizeCache
164
+
}
165
+
166
+
func (x *Commit) Reset() {
167
+
*x = Commit{}
168
+
mi := &file_vylet_kafka_proto_msgTypes[1]
169
+
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
170
+
ms.StoreMessageInfo(mi)
171
+
}
172
+
173
+
func (x *Commit) String() string {
174
+
return protoimpl.X.MessageStringOf(x)
175
+
}
176
+
177
+
func (*Commit) ProtoMessage() {}
178
+
179
+
func (x *Commit) ProtoReflect() protoreflect.Message {
180
+
mi := &file_vylet_kafka_proto_msgTypes[1]
181
+
if x != nil {
182
+
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
183
+
if ms.LoadMessageInfo() == nil {
184
+
ms.StoreMessageInfo(mi)
185
+
}
186
+
return ms
187
+
}
188
+
return mi.MessageOf(x)
189
+
}
190
+
191
+
// Deprecated: Use Commit.ProtoReflect.Descriptor instead.
192
+
func (*Commit) Descriptor() ([]byte, []int) {
193
+
return file_vylet_kafka_proto_rawDescGZIP(), []int{1}
194
+
}
195
+
196
+
func (x *Commit) GetRev() string {
197
+
if x != nil {
198
+
return x.Rev
199
+
}
200
+
return ""
201
+
}
202
+
203
+
func (x *Commit) GetOperation() CommitOperation {
204
+
if x != nil {
205
+
return x.Operation
206
+
}
207
+
return CommitOperation_COMMIT_OPERATION_UNSPECIFIED
208
+
}
209
+
210
+
func (x *Commit) GetCollection() string {
211
+
if x != nil {
212
+
return x.Collection
213
+
}
214
+
return ""
215
+
}
216
+
217
+
func (x *Commit) GetRkey() string {
218
+
if x != nil {
219
+
return x.Rkey
220
+
}
221
+
return ""
222
+
}
223
+
224
+
func (x *Commit) GetRecord() []byte {
225
+
if x != nil {
226
+
return x.Record
227
+
}
228
+
return nil
229
+
}
230
+
231
+
func (x *Commit) GetCid() string {
232
+
if x != nil {
233
+
return x.Cid
234
+
}
235
+
return ""
236
+
}
237
+
238
+
type SequenceCursor struct {
239
+
state protoimpl.MessageState `protogen:"open.v1"`
240
+
Sequence int64 `protobuf:"varint,1,opt,name=sequence,proto3" json:"sequence,omitempty"`
241
+
SavedOnExit bool `protobuf:"varint,2,opt,name=saved_on_exit,json=savedOnExit,proto3" json:"saved_on_exit,omitempty"`
242
+
unknownFields protoimpl.UnknownFields
243
+
sizeCache protoimpl.SizeCache
244
+
}
245
+
246
+
func (x *SequenceCursor) Reset() {
247
+
*x = SequenceCursor{}
248
+
mi := &file_vylet_kafka_proto_msgTypes[2]
249
+
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
250
+
ms.StoreMessageInfo(mi)
251
+
}
252
+
253
+
func (x *SequenceCursor) String() string {
254
+
return protoimpl.X.MessageStringOf(x)
255
+
}
256
+
257
+
func (*SequenceCursor) ProtoMessage() {}
258
+
259
+
func (x *SequenceCursor) ProtoReflect() protoreflect.Message {
260
+
mi := &file_vylet_kafka_proto_msgTypes[2]
261
+
if x != nil {
262
+
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
263
+
if ms.LoadMessageInfo() == nil {
264
+
ms.StoreMessageInfo(mi)
265
+
}
266
+
return ms
267
+
}
268
+
return mi.MessageOf(x)
269
+
}
270
+
271
+
// Deprecated: Use SequenceCursor.ProtoReflect.Descriptor instead.
272
+
func (*SequenceCursor) Descriptor() ([]byte, []int) {
273
+
return file_vylet_kafka_proto_rawDescGZIP(), []int{2}
274
+
}
275
+
276
+
func (x *SequenceCursor) GetSequence() int64 {
277
+
if x != nil {
278
+
return x.Sequence
279
+
}
280
+
return 0
281
+
}
282
+
283
+
func (x *SequenceCursor) GetSavedOnExit() bool {
284
+
if x != nil {
285
+
return x.SavedOnExit
286
+
}
287
+
return false
288
+
}
289
+
290
+
var File_vylet_kafka_proto protoreflect.FileDescriptor
291
+
292
+
const file_vylet_kafka_proto_rawDesc = "" +
293
+
"\n" +
294
+
"\x11vylet_kafka.proto\x12\n" +
295
+
"vyletkafka\x1a\x1bbuf/validate/validate.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x80\x02\n" +
296
+
"\rFirehoseEvent\x12\x18\n" +
297
+
"\x03did\x18\x01 \x01(\tB\x06\xbaH\x03\xc8\x01\x01R\x03did\x12@\n" +
298
+
"\ttimestamp\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampB\x06\xbaH\x03\xc8\x01\x01R\ttimestamp\x12/\n" +
299
+
"\x06commit\x18\x03 \x01(\v2\x12.vyletkafka.CommitH\x00R\x06commit\x88\x01\x01\x12\x1d\n" +
300
+
"\aaccount\x18\x04 \x01(\fH\x01R\aaccount\x88\x01\x01\x12\x1f\n" +
301
+
"\bidentity\x18\x05 \x01(\fH\x02R\bidentity\x88\x01\x01B\t\n" +
302
+
"\a_commitB\n" +
303
+
"\n" +
304
+
"\b_accountB\v\n" +
305
+
"\t_identity\"\xb3\x01\n" +
306
+
"\x06Commit\x12\x10\n" +
307
+
"\x03rev\x18\x01 \x01(\tR\x03rev\x129\n" +
308
+
"\toperation\x18\x02 \x01(\x0e2\x1b.vyletkafka.CommitOperationR\toperation\x12\x1e\n" +
309
+
"\n" +
310
+
"collection\x18\x03 \x01(\tR\n" +
311
+
"collection\x12\x12\n" +
312
+
"\x04rkey\x18\x04 \x01(\tR\x04rkey\x12\x16\n" +
313
+
"\x06record\x18\x05 \x01(\fR\x06record\x12\x10\n" +
314
+
"\x03cid\x18\x06 \x01(\tR\x03cid\"P\n" +
315
+
"\x0eSequenceCursor\x12\x1a\n" +
316
+
"\bsequence\x18\x01 \x01(\x03R\bsequence\x12\"\n" +
317
+
"\rsaved_on_exit\x18\x02 \x01(\bR\vsavedOnExit*\x8a\x01\n" +
318
+
"\x0fCommitOperation\x12 \n" +
319
+
"\x1cCOMMIT_OPERATION_UNSPECIFIED\x10\x00\x12\x1b\n" +
320
+
"\x17COMMIT_OPERATION_CREATE\x10\x01\x12\x1b\n" +
321
+
"\x17COMMIT_OPERATION_UPDATE\x10\x02\x12\x1b\n" +
322
+
"\x17COMMIT_OPERATION_DELETE\x10\x03Bx\n" +
323
+
"\x0ecom.vyletkafkaB\x0fVyletKafkaProtoP\x01Z\r./;vyletkafka\xa2\x02\x03VXX\xaa\x02\n" +
324
+
"Vyletkafka\xca\x02\n" +
325
+
"Vyletkafka\xe2\x02\x16Vyletkafka\\GPBMetadata\xea\x02\n" +
326
+
"Vyletkafkab\x06proto3"
327
+
328
+
var (
329
+
file_vylet_kafka_proto_rawDescOnce sync.Once
330
+
file_vylet_kafka_proto_rawDescData []byte
331
+
)
332
+
333
+
func file_vylet_kafka_proto_rawDescGZIP() []byte {
334
+
file_vylet_kafka_proto_rawDescOnce.Do(func() {
335
+
file_vylet_kafka_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_vylet_kafka_proto_rawDesc), len(file_vylet_kafka_proto_rawDesc)))
336
+
})
337
+
return file_vylet_kafka_proto_rawDescData
338
+
}
339
+
340
+
var file_vylet_kafka_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
341
+
var file_vylet_kafka_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
342
+
var file_vylet_kafka_proto_goTypes = []any{
343
+
(CommitOperation)(0), // 0: vyletkafka.CommitOperation
344
+
(*FirehoseEvent)(nil), // 1: vyletkafka.FirehoseEvent
345
+
(*Commit)(nil), // 2: vyletkafka.Commit
346
+
(*SequenceCursor)(nil), // 3: vyletkafka.SequenceCursor
347
+
(*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp
348
+
}
349
+
var file_vylet_kafka_proto_depIdxs = []int32{
350
+
4, // 0: vyletkafka.FirehoseEvent.timestamp:type_name -> google.protobuf.Timestamp
351
+
2, // 1: vyletkafka.FirehoseEvent.commit:type_name -> vyletkafka.Commit
352
+
0, // 2: vyletkafka.Commit.operation:type_name -> vyletkafka.CommitOperation
353
+
3, // [3:3] is the sub-list for method output_type
354
+
3, // [3:3] is the sub-list for method input_type
355
+
3, // [3:3] is the sub-list for extension type_name
356
+
3, // [3:3] is the sub-list for extension extendee
357
+
0, // [0:3] is the sub-list for field type_name
358
+
}
359
+
360
+
func init() { file_vylet_kafka_proto_init() }
361
+
func file_vylet_kafka_proto_init() {
362
+
if File_vylet_kafka_proto != nil {
363
+
return
364
+
}
365
+
file_vylet_kafka_proto_msgTypes[0].OneofWrappers = []any{}
366
+
type x struct{}
367
+
out := protoimpl.TypeBuilder{
368
+
File: protoimpl.DescBuilder{
369
+
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
370
+
RawDescriptor: unsafe.Slice(unsafe.StringData(file_vylet_kafka_proto_rawDesc), len(file_vylet_kafka_proto_rawDesc)),
371
+
NumEnums: 1,
372
+
NumMessages: 3,
373
+
NumExtensions: 0,
374
+
NumServices: 0,
375
+
},
376
+
GoTypes: file_vylet_kafka_proto_goTypes,
377
+
DependencyIndexes: file_vylet_kafka_proto_depIdxs,
378
+
EnumInfos: file_vylet_kafka_proto_enumTypes,
379
+
MessageInfos: file_vylet_kafka_proto_msgTypes,
380
+
}.Build()
381
+
File_vylet_kafka_proto = out.File
382
+
file_vylet_kafka_proto_goTypes = nil
383
+
file_vylet_kafka_proto_depIdxs = nil
384
+
}
+43
bus/proto/vylet_kafka.proto
+43
bus/proto/vylet_kafka.proto
···
1
+
syntax = "proto3";
2
+
3
+
package vyletkafka;
4
+
option go_package = "./;vyletkafka";
5
+
6
+
import "buf/validate/validate.proto";
7
+
8
+
import "google/protobuf/timestamp.proto";
9
+
10
+
message FirehoseEvent {
11
+
string did = 1 [
12
+
(buf.validate.field).required = true
13
+
];
14
+
15
+
google.protobuf.Timestamp timestamp = 2 [
16
+
(buf.validate.field).required = true
17
+
];
18
+
19
+
optional Commit commit = 3;
20
+
optional bytes account = 4;
21
+
optional bytes identity = 5;
22
+
}
23
+
24
+
message Commit {
25
+
string rev = 1;
26
+
CommitOperation operation = 2;
27
+
string collection = 3;
28
+
string rkey = 4;
29
+
bytes record = 5; // json.RawMessage as opaque bytes
30
+
string cid = 6;
31
+
}
32
+
33
+
enum CommitOperation {
34
+
COMMIT_OPERATION_UNSPECIFIED = 0;
35
+
COMMIT_OPERATION_CREATE = 1;
36
+
COMMIT_OPERATION_UPDATE = 2;
37
+
COMMIT_OPERATION_DELETE = 3;
38
+
}
39
+
40
+
message SequenceCursor {
41
+
int64 sequence = 1;
42
+
bool saved_on_exit = 2;
43
+
}
+49
-1
cmd/bus/firehose/main.go
+49
-1
cmd/bus/firehose/main.go
···
1
1
package main
2
2
3
3
import (
4
+
"context"
5
+
"fmt"
4
6
"log"
5
7
"os"
6
8
9
+
"github.com/bluesky-social/go-util/pkg/telemetry"
7
10
"github.com/urfave/cli/v2"
11
+
kafkafirehose "github.com/vylet-app/go/bus/firehose"
8
12
)
9
13
10
14
func main() {
11
15
app := cli.App{
12
-
Name: "kafka-firehose",
16
+
Name: "kafka-firehose",
17
+
Flags: []cli.Flag{
18
+
telemetry.CLIFlagDebug,
19
+
telemetry.CLIFlagMetricsListenAddress,
20
+
&cli.StringSliceFlag{
21
+
Name: "desired-collections",
22
+
EnvVars: []string{"KAFKA_FIREHOSE_DESIRED_COLLECTIONS"},
23
+
},
24
+
&cli.StringFlag{
25
+
Name: "websocket-host",
26
+
EnvVars: []string{"KAFKA_FIREHOSE_WEBSOCKET_HOST"},
27
+
Value: "wss://bsky.network",
28
+
},
29
+
&cli.StringSliceFlag{
30
+
Name: "bootstrap-servers",
31
+
EnvVars: []string{"KAFKA_FIREHOSE_BOOTSTRAP_SERVERS"},
32
+
Value: cli.NewStringSlice("localhost:9092"),
33
+
},
34
+
&cli.StringFlag{
35
+
Name: "output-topic",
36
+
EnvVars: []string{"KAFKA_FIREHOSE_OUTPUT_TOPIC"},
37
+
Value: "firehose-events-prod",
38
+
},
39
+
},
13
40
Action: run,
14
41
}
15
42
···
19
46
}
20
47
21
48
func run(cmd *cli.Context) error {
49
+
ctx := context.Background()
50
+
51
+
logger := telemetry.StartLogger(cmd)
52
+
telemetry.StartMetrics(cmd)
53
+
54
+
kf, err := kafkafirehose.New(ctx, &kafkafirehose.Args{
55
+
Logger: logger,
56
+
57
+
DesiredCollections: cmd.StringSlice("desired-collections"),
58
+
WebsocketHost: cmd.String("websocket-host"),
59
+
BootstrapServers: cmd.StringSlice("bootstrap-servers"),
60
+
OutputTopic: cmd.String("output-topic"),
61
+
})
62
+
if err != nil {
63
+
return fmt.Errorf("failed to create new kafka firehose: %w", err)
64
+
}
65
+
66
+
if err := kf.Run(ctx); err != nil {
67
+
return err
68
+
}
69
+
22
70
return nil
23
71
}
+86
-1
go.mod
+86
-1
go.mod
···
2
2
3
3
go 1.25.5
4
4
5
-
require github.com/urfave/cli/v2 v2.27.7
5
+
require (
6
+
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.9-20250717185734-6c6e0d3c608e.1
7
+
github.com/bluesky-social/go-util v0.0.0-20251012040650-2ebbf57f5934
8
+
github.com/bluesky-social/indigo v0.0.0-20251206005924-d49b45419635
9
+
github.com/gorilla/websocket v1.5.1
10
+
github.com/urfave/cli/v2 v2.27.7
11
+
google.golang.org/protobuf v1.36.9
12
+
)
6
13
7
14
require (
15
+
github.com/RussellLuo/slidingwindow v0.0.0-20200528002341-535bb99d338b // indirect
16
+
github.com/beorn7/perks v1.0.1 // indirect
17
+
github.com/cespare/xxhash/v2 v2.3.0 // indirect
18
+
github.com/confluentinc/confluent-kafka-go/v2 v2.8.0 // indirect
8
19
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
20
+
github.com/earthboundkid/versioninfo/v2 v2.24.1 // indirect
21
+
github.com/felixge/httpsnoop v1.0.4 // indirect
22
+
github.com/go-logr/logr v1.4.1 // indirect
23
+
github.com/go-logr/stdr v1.2.2 // indirect
24
+
github.com/gogo/protobuf v1.3.2 // indirect
25
+
github.com/google/uuid v1.6.0 // indirect
26
+
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
27
+
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
28
+
github.com/hashicorp/golang-lru v1.0.2 // indirect
29
+
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
30
+
github.com/ipfs/bbloom v0.0.4 // indirect
31
+
github.com/ipfs/go-block-format v0.2.0 // indirect
32
+
github.com/ipfs/go-blockservice v0.5.2 // indirect
33
+
github.com/ipfs/go-cid v0.4.1 // indirect
34
+
github.com/ipfs/go-datastore v0.6.0 // indirect
35
+
github.com/ipfs/go-ipfs-blockstore v1.3.1 // indirect
36
+
github.com/ipfs/go-ipfs-ds-help v1.1.1 // indirect
37
+
github.com/ipfs/go-ipfs-exchange-interface v0.2.1 // indirect
38
+
github.com/ipfs/go-ipfs-util v0.0.3 // indirect
39
+
github.com/ipfs/go-ipld-cbor v0.1.0 // indirect
40
+
github.com/ipfs/go-ipld-format v0.6.0 // indirect
41
+
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect
42
+
github.com/ipfs/go-log v1.0.5 // indirect
43
+
github.com/ipfs/go-log/v2 v2.5.1 // indirect
44
+
github.com/ipfs/go-merkledag v0.11.0 // indirect
45
+
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
46
+
github.com/ipfs/go-verifcid v0.0.3 // indirect
47
+
github.com/ipld/go-car v0.6.1-0.20230509095817-92d28eb23ba4 // indirect
48
+
github.com/ipld/go-codec-dagpb v1.6.0 // indirect
49
+
github.com/ipld/go-ipld-prime v0.21.0 // indirect
50
+
github.com/jbenet/goprocess v0.1.4 // indirect
51
+
github.com/jinzhu/inflection v1.0.0 // indirect
52
+
github.com/jinzhu/now v1.1.5 // indirect
53
+
github.com/klauspost/compress v1.18.0 // indirect
54
+
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
55
+
github.com/mattn/go-isatty v0.0.20 // indirect
56
+
github.com/minio/sha256-simd v1.0.1 // indirect
57
+
github.com/mr-tron/base58 v1.2.0 // indirect
58
+
github.com/multiformats/go-base32 v0.1.0 // indirect
59
+
github.com/multiformats/go-base36 v0.2.0 // indirect
60
+
github.com/multiformats/go-multibase v0.2.0 // indirect
61
+
github.com/multiformats/go-multihash v0.2.3 // indirect
62
+
github.com/multiformats/go-varint v0.0.7 // indirect
63
+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
64
+
github.com/opentracing/opentracing-go v1.2.0 // indirect
65
+
github.com/pierrec/lz4/v4 v4.1.22 // indirect
66
+
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect
67
+
github.com/prometheus/client_golang v1.23.2 // indirect
68
+
github.com/prometheus/client_model v0.6.2 // indirect
69
+
github.com/prometheus/common v0.66.1 // indirect
70
+
github.com/prometheus/procfs v0.16.1 // indirect
71
+
github.com/rs/xid v1.6.0 // indirect
9
72
github.com/russross/blackfriday/v2 v2.1.0 // indirect
73
+
github.com/spaolacci/murmur3 v1.1.0 // indirect
74
+
github.com/twmb/franz-go v1.19.5 // indirect
75
+
github.com/twmb/franz-go/pkg/kadm v1.16.1 // indirect
76
+
github.com/twmb/franz-go/pkg/kmsg v1.11.2 // indirect
77
+
github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e // indirect
10
78
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
79
+
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect
80
+
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect
81
+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
82
+
go.opentelemetry.io/otel v1.24.0 // indirect
83
+
go.opentelemetry.io/otel/metric v1.24.0 // indirect
84
+
go.opentelemetry.io/otel/trace v1.24.0 // indirect
85
+
go.uber.org/atomic v1.11.0 // indirect
86
+
go.uber.org/multierr v1.11.0 // indirect
87
+
go.uber.org/zap v1.26.0 // indirect
88
+
go.yaml.in/yaml/v2 v2.4.2 // indirect
89
+
golang.org/x/crypto v0.41.0 // indirect
90
+
golang.org/x/net v0.43.0 // indirect
91
+
golang.org/x/sys v0.35.0 // indirect
92
+
golang.org/x/time v0.6.0 // indirect
93
+
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
94
+
gorm.io/gorm v1.25.9 // indirect
95
+
lukechampine.com/blake3 v1.2.1 // indirect
11
96
)
+382
go.sum
+382
go.sum
···
1
+
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.9-20250717185734-6c6e0d3c608e.1 h1:u98oQG8CHYBrOWrYdqbyNpKz4Pw02ssv03DsTInnXn8=
2
+
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.9-20250717185734-6c6e0d3c608e.1/go.mod h1:aY3zbkNan5F+cGm9lITDP6oxJIwu0dn9KjJuJjWaHkg=
3
+
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
4
+
github.com/RussellLuo/slidingwindow v0.0.0-20200528002341-535bb99d338b h1:5/++qT1/z812ZqBvqQt6ToRswSuPZ/B33m6xVHRzADU=
5
+
github.com/RussellLuo/slidingwindow v0.0.0-20200528002341-535bb99d338b/go.mod h1:4+EPqMRApwwE/6yo6CxiHoSnBzjRr3jsqer7frxP8y4=
6
+
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
7
+
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
8
+
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
9
+
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
10
+
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
11
+
github.com/bluesky-social/go-util v0.0.0-20251012040650-2ebbf57f5934 h1:btHMur2kTRgWEnCHn6LaI3BE9YRgsqTpwpJ1UdB7VEk=
12
+
github.com/bluesky-social/go-util v0.0.0-20251012040650-2ebbf57f5934/go.mod h1:LWamyZfbQGW7PaVc5jumFfjgrshJ5mXgDUnR6fK7+BI=
13
+
github.com/bluesky-social/indigo v0.0.0-20251206005924-d49b45419635 h1:kNeRrgGJH2g5OvjLqtaQ744YXqduliZYpFkJ/ld47c0=
14
+
github.com/bluesky-social/indigo v0.0.0-20251206005924-d49b45419635/go.mod h1:Pm2I1+iDXn/hLbF7XCg/DsZi6uDCiOo7hZGWprSM7k0=
15
+
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
16
+
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
17
+
github.com/confluentinc/confluent-kafka-go/v2 v2.8.0 h1:0HlcSNWg4LpLA9nIjzUMIqWHI+w0S68UN7alXAc3TeA=
18
+
github.com/confluentinc/confluent-kafka-go/v2 v2.8.0/go.mod h1:hScqtFIGUI1wqHIgM3mjoqEou4VweGGGX7dMpcUKves=
19
+
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
1
20
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
2
21
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
22
+
github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0=
23
+
github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis=
24
+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
25
+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
26
+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
27
+
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
28
+
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
29
+
github.com/earthboundkid/versioninfo/v2 v2.24.1 h1:SJTMHaoUx3GzjjnUO1QzP3ZXK6Ee/nbWyCm58eY3oUg=
30
+
github.com/earthboundkid/versioninfo/v2 v2.24.1/go.mod h1:VcWEooDEuyUJnMfbdTh0uFN4cfEIg+kHMuWB2CDCLjw=
31
+
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
32
+
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
33
+
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
34
+
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
35
+
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
36
+
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
37
+
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
38
+
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
39
+
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
40
+
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
41
+
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
42
+
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
43
+
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
44
+
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
45
+
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
46
+
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
47
+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
48
+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
49
+
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
50
+
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
51
+
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
52
+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
53
+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
54
+
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
55
+
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
56
+
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
57
+
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
58
+
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
59
+
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
60
+
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
61
+
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
62
+
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
63
+
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
64
+
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
65
+
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
66
+
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
67
+
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
68
+
github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ=
69
+
github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y=
70
+
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
71
+
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
72
+
github.com/ipfs/go-bitswap v0.11.0 h1:j1WVvhDX1yhG32NTC9xfxnqycqYIlhzEzLXG/cU1HyQ=
73
+
github.com/ipfs/go-bitswap v0.11.0/go.mod h1:05aE8H3XOU+LXpTedeAS0OZpcO1WFsj5niYQH9a1Tmk=
74
+
github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
75
+
github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
76
+
github.com/ipfs/go-blockservice v0.5.2 h1:in9Bc+QcXwd1apOVM7Un9t8tixPKdaHQFdLSUM1Xgk8=
77
+
github.com/ipfs/go-blockservice v0.5.2/go.mod h1:VpMblFEqG67A/H2sHKAemeH9vlURVavlysbdUI632yk=
78
+
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
79
+
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
80
+
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
81
+
github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
82
+
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
83
+
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
84
+
github.com/ipfs/go-ipfs-blockstore v1.3.1 h1:cEI9ci7V0sRNivqaOr0elDsamxXFxJMMMy7PTTDQNsQ=
85
+
github.com/ipfs/go-ipfs-blockstore v1.3.1/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE=
86
+
github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ=
87
+
github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk=
88
+
github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ=
89
+
github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
90
+
github.com/ipfs/go-ipfs-ds-help v1.1.1 h1:B5UJOH52IbcfS56+Ul+sv8jnIV10lbjLF5eOO0C66Nw=
91
+
github.com/ipfs/go-ipfs-ds-help v1.1.1/go.mod h1:75vrVCkSdSFidJscs8n4W+77AtTpCIAdDGAwjitJMIo=
92
+
github.com/ipfs/go-ipfs-exchange-interface v0.2.1 h1:jMzo2VhLKSHbVe+mHNzYgs95n0+t0Q69GQ5WhRDZV/s=
93
+
github.com/ipfs/go-ipfs-exchange-interface v0.2.1/go.mod h1:MUsYn6rKbG6CTtsDp+lKJPmVt3ZrCViNyH3rfPGsZ2E=
94
+
github.com/ipfs/go-ipfs-exchange-offline v0.3.0 h1:c/Dg8GDPzixGd0MC8Jh6mjOwU57uYokgWRFidfvEkuA=
95
+
github.com/ipfs/go-ipfs-exchange-offline v0.3.0/go.mod h1:MOdJ9DChbb5u37M1IcbrRB02e++Z7521fMxqCNRrz9s=
96
+
github.com/ipfs/go-ipfs-pq v0.0.2 h1:e1vOOW6MuOwG2lqxcLA+wEn93i/9laCY8sXAw76jFOY=
97
+
github.com/ipfs/go-ipfs-pq v0.0.2/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY=
98
+
github.com/ipfs/go-ipfs-routing v0.3.0 h1:9W/W3N+g+y4ZDeffSgqhgo7BsBSJwPMcyssET9OWevc=
99
+
github.com/ipfs/go-ipfs-routing v0.3.0/go.mod h1:dKqtTFIql7e1zYsEuWLyuOU+E0WJWW8JjbTPLParDWo=
100
+
github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0=
101
+
github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs=
102
+
github.com/ipfs/go-ipld-cbor v0.1.0 h1:dx0nS0kILVivGhfWuB6dUpMa/LAwElHPw1yOGYopoYs=
103
+
github.com/ipfs/go-ipld-cbor v0.1.0/go.mod h1:U2aYlmVrJr2wsUBU67K4KgepApSZddGRDWBYR0H4sCk=
104
+
github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten1F5U=
105
+
github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg=
106
+
github.com/ipfs/go-ipld-legacy v0.2.1 h1:mDFtrBpmU7b//LzLSypVrXsD8QxkEWxu5qVxN99/+tk=
107
+
github.com/ipfs/go-ipld-legacy v0.2.1/go.mod h1:782MOUghNzMO2DER0FlBR94mllfdCJCkTtDtPM51otM=
108
+
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
109
+
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
110
+
github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
111
+
github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
112
+
github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
113
+
github.com/ipfs/go-merkledag v0.11.0 h1:DgzwK5hprESOzS4O1t/wi6JDpyVQdvm9Bs59N/jqfBY=
114
+
github.com/ipfs/go-merkledag v0.11.0/go.mod h1:Q4f/1ezvBiJV0YCIXvt51W/9/kqJGH4I1LsA7+djsM4=
115
+
github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg=
116
+
github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY=
117
+
github.com/ipfs/go-peertaskqueue v0.8.0 h1:JyNO144tfu9bx6Hpo119zvbEL9iQ760FHOiJYsUjqaU=
118
+
github.com/ipfs/go-peertaskqueue v0.8.0/go.mod h1:cz8hEnnARq4Du5TGqiWKgMr/BOSQ5XOgMOh1K5YYKKM=
119
+
github.com/ipfs/go-verifcid v0.0.3 h1:gmRKccqhWDocCRkC+a59g5QW7uJw5bpX9HWBevXa0zs=
120
+
github.com/ipfs/go-verifcid v0.0.3/go.mod h1:gcCtGniVzelKrbk9ooUSX/pM3xlH73fZZJDzQJRvOUw=
121
+
github.com/ipld/go-car v0.6.1-0.20230509095817-92d28eb23ba4 h1:oFo19cBmcP0Cmg3XXbrr0V/c+xU9U1huEZp8+OgBzdI=
122
+
github.com/ipld/go-car v0.6.1-0.20230509095817-92d28eb23ba4/go.mod h1:6nkFF8OmR5wLKBzRKi7/YFJpyYR7+oEn1DX+mMWnlLA=
123
+
github.com/ipld/go-car/v2 v2.13.1 h1:KnlrKvEPEzr5IZHKTXLAEub+tPrzeAFQVRlSQvuxBO4=
124
+
github.com/ipld/go-car/v2 v2.13.1/go.mod h1:QkdjjFNGit2GIkpQ953KBwowuoukoM75nP/JI1iDJdo=
125
+
github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc=
126
+
github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s=
127
+
github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
128
+
github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ=
129
+
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
130
+
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
131
+
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
132
+
github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o=
133
+
github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
134
+
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
135
+
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
136
+
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
137
+
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
138
+
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
139
+
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
140
+
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
141
+
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
142
+
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
143
+
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
144
+
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
145
+
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
146
+
github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8=
147
+
github.com/koron/go-ssdp v0.0.3/go.mod h1:b2MxI6yh02pKrsyNoQUsk4+YNikaGhe4894J+Q5lDvA=
148
+
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
149
+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
150
+
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
151
+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
152
+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
153
+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
154
+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
155
+
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
156
+
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
157
+
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
158
+
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
159
+
github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
160
+
github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
161
+
github.com/libp2p/go-libp2p v0.22.0 h1:2Tce0kHOp5zASFKJbNzRElvh0iZwdtG5uZheNW8chIw=
162
+
github.com/libp2p/go-libp2p v0.22.0/go.mod h1:UDolmweypBSjQb2f7xutPnwZ/fxioLbMBxSjRksxxU4=
163
+
github.com/libp2p/go-libp2p-asn-util v0.2.0 h1:rg3+Os8jbnO5DxkC7K/Utdi+DkY3q/d1/1q+8WeNAsw=
164
+
github.com/libp2p/go-libp2p-asn-util v0.2.0/go.mod h1:WoaWxbHKBymSN41hWSq/lGKJEca7TNm58+gGJi2WsLI=
165
+
github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0=
166
+
github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk=
167
+
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
168
+
github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
169
+
github.com/libp2p/go-msgio v0.2.0 h1:W6shmB+FeynDrUVl2dgFQvzfBZcXiyqY4VmpQLu9FqU=
170
+
github.com/libp2p/go-msgio v0.2.0/go.mod h1:dBVM1gW3Jk9XqHkU4eKdGvVHdLa51hoGfll6jMJMSlY=
171
+
github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg=
172
+
github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM=
173
+
github.com/libp2p/go-netroute v0.2.0 h1:0FpsbsvuSnAhXFnCY0VLFbJOzaK0VnP0r1QT/o4nWRE=
174
+
github.com/libp2p/go-netroute v0.2.0/go.mod h1:Vio7LTzZ+6hoT4CMZi5/6CpY3Snzh2vgZhWgxMNwlQI=
175
+
github.com/libp2p/go-openssl v0.1.0 h1:LBkKEcUv6vtZIQLVTegAil8jbNpJErQ9AnT+bWV+Ooo=
176
+
github.com/libp2p/go-openssl v0.1.0/go.mod h1:OiOxwPpL3n4xlenjx2h7AwSGaFSC/KZvf6gNdOBQMtc=
177
+
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
178
+
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
179
+
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
180
+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
181
+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
182
+
github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0=
183
+
github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
184
+
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
185
+
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
186
+
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
187
+
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
188
+
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
189
+
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
190
+
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
191
+
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
192
+
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
193
+
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
194
+
github.com/multiformats/go-multiaddr v0.7.0 h1:gskHcdaCyPtp9XskVwtvEeQOG465sCohbQIirSyqxrc=
195
+
github.com/multiformats/go-multiaddr v0.7.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs=
196
+
github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A=
197
+
github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk=
198
+
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
199
+
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
200
+
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
201
+
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
202
+
github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg=
203
+
github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k=
204
+
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
205
+
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
206
+
github.com/multiformats/go-multistream v0.3.3 h1:d5PZpjwRgVlbwfdTDjife7XszfZd8KYWfROYFlGcR8o=
207
+
github.com/multiformats/go-multistream v0.3.3/go.mod h1:ODRoqamLUsETKS9BNcII4gcRsJBU5VAwRIv7O39cEXg=
208
+
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
209
+
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
210
+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
211
+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
212
+
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
213
+
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
214
+
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk=
215
+
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw=
216
+
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
217
+
github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
218
+
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
219
+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
220
+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
221
+
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0=
222
+
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
223
+
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
224
+
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
225
+
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
226
+
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
227
+
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
228
+
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
229
+
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
230
+
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
231
+
github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg=
232
+
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
233
+
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
234
+
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
235
+
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
236
+
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
237
+
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
238
+
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
3
239
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
4
240
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
241
+
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
242
+
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
243
+
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
244
+
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
245
+
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
246
+
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=
247
+
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
248
+
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
249
+
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
250
+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
251
+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
252
+
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
253
+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
254
+
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
255
+
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
256
+
github.com/twmb/franz-go v1.19.5 h1:W7+o8D0RsQsedqib71OVlLeZ0zI6CbFra7yTYhZTs5Y=
257
+
github.com/twmb/franz-go v1.19.5/go.mod h1:4kFJ5tmbbl7asgwAGVuyG1ZMx0NNpYk7EqflvWfPCpM=
258
+
github.com/twmb/franz-go/pkg/kadm v1.16.1 h1:IEkrhTljgLHJ0/hT/InhXGjPdmWfFvxp7o/MR7vJ8cw=
259
+
github.com/twmb/franz-go/pkg/kadm v1.16.1/go.mod h1:Ue/ye1cc9ipsQFg7udFbbGiFNzQMqiH73fGC2y0rwyc=
260
+
github.com/twmb/franz-go/pkg/kmsg v1.11.2 h1:hIw75FpwcAjgeyfIGFqivAvwC5uNIOWRGvQgZhH4mhg=
261
+
github.com/twmb/franz-go/pkg/kmsg v1.11.2/go.mod h1:CFfkkLysDNmukPYhGzuUcDtf46gQSqCZHMW1T4Z+wDE=
262
+
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
5
263
github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=
6
264
github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=
265
+
github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s=
266
+
github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y=
267
+
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
268
+
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
269
+
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0=
270
+
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ=
271
+
github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e h1:28X54ciEwwUxyHn9yrZfl5ojgF4CBNLWX7LR0rvBkf4=
272
+
github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so=
7
273
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
8
274
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
275
+
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
276
+
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
277
+
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
278
+
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b h1:CzigHMRySiX3drau9C6Q5CAbNIApmLdat5jPMqChvDA=
279
+
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8=
280
+
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q=
281
+
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I=
282
+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
283
+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
284
+
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
285
+
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
286
+
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
287
+
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
288
+
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
289
+
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
290
+
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
291
+
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
292
+
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
293
+
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
294
+
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
295
+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
296
+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
297
+
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
298
+
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
299
+
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
300
+
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
301
+
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
302
+
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
303
+
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
304
+
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
305
+
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
306
+
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
307
+
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
308
+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
309
+
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
310
+
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
311
+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
312
+
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
313
+
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
314
+
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
315
+
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
316
+
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
317
+
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
318
+
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
319
+
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
320
+
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
321
+
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
322
+
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
323
+
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
324
+
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
325
+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
326
+
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
327
+
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
328
+
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
329
+
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
330
+
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
331
+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
332
+
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
333
+
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
334
+
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
335
+
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
336
+
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
337
+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
338
+
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
339
+
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
340
+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
341
+
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
342
+
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
343
+
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
344
+
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
345
+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
346
+
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
347
+
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
348
+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
349
+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
350
+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
351
+
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
352
+
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
353
+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
354
+
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
355
+
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
356
+
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
357
+
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
358
+
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
359
+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
360
+
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
361
+
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
362
+
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
363
+
golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
364
+
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
365
+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
366
+
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
367
+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
368
+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
369
+
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
370
+
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
371
+
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
372
+
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
373
+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
374
+
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
375
+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
376
+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
377
+
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
378
+
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
379
+
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
380
+
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
381
+
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
382
+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
383
+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
384
+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
385
+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
386
+
gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8=
387
+
gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
388
+
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
389
+
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
390
+
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=