From 48e2ba08f36a46064eca7285d1e751b5df9735c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Sm=C3=B3=C5=82ka?= Date: Tue, 29 Oct 2024 15:59:01 +0100 Subject: [PATCH] Add more docs on requeue (#509) --- .../delayed-messages/go.mod | 4 +- .../delayed-messages/go.sum | 10 ++-- .../delayed-messages/main.go | 13 ++--- .../delayed-requeue/go.mod | 4 +- .../delayed-requeue/go.sum | 10 ++-- .../delayed-requeue/main.go | 35 ++++++----- docs/build.sh | 2 + .../content/advanced/requeuing-after-error.md | 55 ++++++++++++++++++ docs/content/docs/getting-started.md | 1 - docs/content/pubsubs/sql.md | 35 ++++++++--- ...9940_c0fe83760c1bebd5a39d4ddb7fce622e.webp | Bin 0 -> 16278 bytes ...3739_cb9243f2e37f830fb14160ae4284ce39.webp | Bin 0 -> 13512 bytes tools/pq/go.mod | 6 +- tools/pq/go.sum | 2 + 14 files changed, 123 insertions(+), 54 deletions(-) create mode 100644 docs/content/advanced/requeuing-after-error.md create mode 100644 docs/resources/_gen/images/_hu70523d59fb738bec5c06336403a46531_39940_c0fe83760c1bebd5a39d4ddb7fce622e.webp create mode 100644 docs/resources/_gen/images/_hu89002a090cbbd5e6897ae6b591dddabc_33739_cb9243f2e37f830fb14160ae4284ce39.webp diff --git a/_examples/real-world-examples/delayed-messages/go.mod b/_examples/real-world-examples/delayed-messages/go.mod index ee8d58d6d..f16b3362b 100644 --- a/_examples/real-world-examples/delayed-messages/go.mod +++ b/_examples/real-world-examples/delayed-messages/go.mod @@ -3,9 +3,9 @@ module delayed-messsages go 1.23.0 require ( - github.com/ThreeDotsLabs/watermill v1.4.0-rc.1.0.20241024100330-cb068b72e948 + github.com/ThreeDotsLabs/watermill v1.4.0-rc.2 github.com/ThreeDotsLabs/watermill-redisstream v1.4.2 - github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-20241024102321-584a6f7dab93 + github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-rc.1 github.com/brianvoe/gofakeit/v6 v6.28.0 github.com/google/uuid v1.6.0 github.com/lib/pq v1.10.2 diff --git a/_examples/real-world-examples/delayed-messages/go.sum b/_examples/real-world-examples/delayed-messages/go.sum index 841fdf6a2..2fdf15843 100644 --- a/_examples/real-world-examples/delayed-messages/go.sum +++ b/_examples/real-world-examples/delayed-messages/go.sum @@ -1,13 +1,11 @@ github.com/Rican7/retry v0.3.1 h1:scY4IbO8swckzoA/11HgBwaZRJEyY9vaNJshcdhp1Mc= github.com/Rican7/retry v0.3.1/go.mod h1:CxSDrhAyXmTMeEuRAnArMu1FHu48vtfjLREWqVl7Vw0= -github.com/ThreeDotsLabs/watermill v1.4.0-rc.1.0.20241024100330-cb068b72e948 h1:b8qRHpWtlO94x6dVzSulrO2znSQqz8iYsxUyrdTixHo= -github.com/ThreeDotsLabs/watermill v1.4.0-rc.1.0.20241024100330-cb068b72e948/go.mod h1:lBnrLbxOjeMRgcJbv+UiZr8Ylz8RkJ4m6i/VN/Nk+to= +github.com/ThreeDotsLabs/watermill v1.4.0-rc.2 h1:K62uIAKOkCHTXtAwY+Nj95vyLR0y25UMBsbf/FuWCeQ= +github.com/ThreeDotsLabs/watermill v1.4.0-rc.2/go.mod h1:lBnrLbxOjeMRgcJbv+UiZr8Ylz8RkJ4m6i/VN/Nk+to= github.com/ThreeDotsLabs/watermill-redisstream v1.4.2 h1:FY6tsBcbhbJpKDOssU4bfybstqY0hQHwiZmVq9qyILQ= github.com/ThreeDotsLabs/watermill-redisstream v1.4.2/go.mod h1:69++855LyB+ckYDe60PiJLBcUrpckfDE2WwyzuVJRCk= -github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-20241024101952-75257d7d0602 h1:CKdW3wb3+C36mMa44DF53KUyM5L6mGOjI3hikBOlAl4= -github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-20241024101952-75257d7d0602/go.mod h1:GMWcpauehgI40EeoKPxLnXBWjT7oOm7dJfzk5uU4IOc= -github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-20241024102321-584a6f7dab93 h1:KeRk2EG5AtdxfpjqIVPigZqscMvIcy0E2h8k7y38OAE= -github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-20241024102321-584a6f7dab93/go.mod h1:GMWcpauehgI40EeoKPxLnXBWjT7oOm7dJfzk5uU4IOc= +github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-rc.1 h1:uYfnh1EoqXrzHu+bX/TboRyv4ou+EFcmkC1MABeQ0lI= +github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-rc.1/go.mod h1:ttA/lhzSh0YyDkosq1Cgc7IYz6Arrba0jIWfdnON0WA= github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4= github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= diff --git a/_examples/real-world-examples/delayed-messages/main.go b/_examples/real-world-examples/delayed-messages/main.go index 520235274..a0cd483ea 100644 --- a/_examples/real-world-examples/delayed-messages/main.go +++ b/_examples/real-world-examples/delayed-messages/main.go @@ -4,6 +4,7 @@ import ( "context" stdSQL "database/sql" "fmt" + "strings" "time" "github.com/brianvoe/gofakeit/v6" @@ -115,7 +116,7 @@ func main() { cqrs.NewEventHandler( "OnOrderPlacedHandler", func(ctx context.Context, event *OrderPlaced) error { - fmt.Printf("Received order placed from %v\n", event.Customer.Name) + fmt.Printf("💰 Received order from %v <%v>\n", event.Customer.Name, event.Customer.Email) cmd := SendFeedbackForm{ To: event.Customer.Email, @@ -142,10 +143,7 @@ func main() { cqrs.NewCommandHandler( "OnSendFeedbackForm", func(ctx context.Context, cmd *SendFeedbackForm) error { - msg := fmt.Sprintf("Hello %s! It's been a while since you placed your order, how did you like it? Let us know!", cmd.Name) - - fmt.Println("Sending feedback form to:", cmd.To) - fmt.Println("\tMessage:", msg) + fmt.Printf("📧 Sending feedback form to %v <%v>\n", cmd.Name, cmd.To) // In a real world scenario, we would send an email to the customer here @@ -188,11 +186,12 @@ func main() { <-router.Running() for { + name := gofakeit.FirstName() e := OrderPlaced{ OrderID: uuid.NewString(), Customer: Customer{ - Name: gofakeit.FirstName(), - Email: gofakeit.Email(), + Name: name, + Email: fmt.Sprintf("%v@%v", strings.ToLower(name), gofakeit.DomainName()), }, } diff --git a/_examples/real-world-examples/delayed-requeue/go.mod b/_examples/real-world-examples/delayed-requeue/go.mod index f76ffb215..78b5e2376 100644 --- a/_examples/real-world-examples/delayed-requeue/go.mod +++ b/_examples/real-world-examples/delayed-requeue/go.mod @@ -3,9 +3,9 @@ module delayed-requeue go 1.23.0 require ( - github.com/ThreeDotsLabs/watermill v1.4.0-rc.1.0.20241024100330-cb068b72e948 + github.com/ThreeDotsLabs/watermill v1.4.0-rc.2 github.com/ThreeDotsLabs/watermill-redisstream v1.4.2 - github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-20241024102321-584a6f7dab93 + github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-rc.1 github.com/brianvoe/gofakeit/v6 v6.28.0 github.com/lib/pq v1.10.9 github.com/redis/go-redis/v9 v9.7.0 diff --git a/_examples/real-world-examples/delayed-requeue/go.sum b/_examples/real-world-examples/delayed-requeue/go.sum index ae0952ed3..7349c7b99 100644 --- a/_examples/real-world-examples/delayed-requeue/go.sum +++ b/_examples/real-world-examples/delayed-requeue/go.sum @@ -2,14 +2,12 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/Rican7/retry v0.3.1 h1:scY4IbO8swckzoA/11HgBwaZRJEyY9vaNJshcdhp1Mc= github.com/Rican7/retry v0.3.1/go.mod h1:CxSDrhAyXmTMeEuRAnArMu1FHu48vtfjLREWqVl7Vw0= -github.com/ThreeDotsLabs/watermill v1.4.0-rc.1.0.20241024100330-cb068b72e948 h1:b8qRHpWtlO94x6dVzSulrO2znSQqz8iYsxUyrdTixHo= -github.com/ThreeDotsLabs/watermill v1.4.0-rc.1.0.20241024100330-cb068b72e948/go.mod h1:lBnrLbxOjeMRgcJbv+UiZr8Ylz8RkJ4m6i/VN/Nk+to= +github.com/ThreeDotsLabs/watermill v1.4.0-rc.2 h1:K62uIAKOkCHTXtAwY+Nj95vyLR0y25UMBsbf/FuWCeQ= +github.com/ThreeDotsLabs/watermill v1.4.0-rc.2/go.mod h1:lBnrLbxOjeMRgcJbv+UiZr8Ylz8RkJ4m6i/VN/Nk+to= github.com/ThreeDotsLabs/watermill-redisstream v1.4.2 h1:FY6tsBcbhbJpKDOssU4bfybstqY0hQHwiZmVq9qyILQ= github.com/ThreeDotsLabs/watermill-redisstream v1.4.2/go.mod h1:69++855LyB+ckYDe60PiJLBcUrpckfDE2WwyzuVJRCk= -github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-20241024101952-75257d7d0602 h1:CKdW3wb3+C36mMa44DF53KUyM5L6mGOjI3hikBOlAl4= -github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-20241024101952-75257d7d0602/go.mod h1:GMWcpauehgI40EeoKPxLnXBWjT7oOm7dJfzk5uU4IOc= -github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-20241024102321-584a6f7dab93 h1:KeRk2EG5AtdxfpjqIVPigZqscMvIcy0E2h8k7y38OAE= -github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-20241024102321-584a6f7dab93/go.mod h1:GMWcpauehgI40EeoKPxLnXBWjT7oOm7dJfzk5uU4IOc= +github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-rc.1 h1:uYfnh1EoqXrzHu+bX/TboRyv4ou+EFcmkC1MABeQ0lI= +github.com/ThreeDotsLabs/watermill-sql/v4 v4.0.0-rc.1/go.mod h1:ttA/lhzSh0YyDkosq1Cgc7IYz6Arrba0jIWfdnON0WA= github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4= github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= diff --git a/_examples/real-world-examples/delayed-requeue/main.go b/_examples/real-world-examples/delayed-requeue/main.go index edd62b588..7aa0a06fd 100644 --- a/_examples/real-world-examples/delayed-requeue/main.go +++ b/_examples/real-world-examples/delayed-requeue/main.go @@ -7,6 +7,8 @@ import ( "math/rand" "time" + "github.com/ThreeDotsLabs/watermill/message/router/middleware" + "github.com/brianvoe/gofakeit/v6" _ "github.com/lib/pq" "github.com/redis/go-redis/v9" @@ -15,8 +17,6 @@ import ( "github.com/ThreeDotsLabs/watermill-redisstream/pkg/redisstream" "github.com/ThreeDotsLabs/watermill-sql/v4/pkg/sql" "github.com/ThreeDotsLabs/watermill/components/cqrs" - "github.com/ThreeDotsLabs/watermill/components/delay" - "github.com/ThreeDotsLabs/watermill/components/requeuer" "github.com/ThreeDotsLabs/watermill/message" ) @@ -40,7 +40,12 @@ func main() { delayedRequeuer, err := sql.NewPostgreSQLDelayedRequeuer(sql.DelayedRequeuerConfig{ DB: db, Publisher: redisPublisher, - Logger: logger, + DelayOnError: &middleware.DelayOnError{ + InitialInterval: 10 * time.Second, + MaxInterval: 3 * time.Minute, + Multiplier: 2, + }, + Logger: logger, }) if err != nil { panic(err) @@ -85,23 +90,13 @@ func main() { cqrs.NewEventHandler( "OnOrderPlacedHandler", func(ctx context.Context, event *OrderPlaced) error { - fmt.Println("Received order placed:", event.OrderID) - - msg := cqrs.OriginalMessageFromCtx(ctx) - retries := msg.Metadata.Get(requeuer.RetriesKey) - delayedUntil := msg.Metadata.Get(delay.DelayedUntilKey) - delayedFor := msg.Metadata.Get(delay.DelayedForKey) - - if retries != "" { - fmt.Println("\tRetries:", retries) - fmt.Println("\tDelayed until:", delayedUntil) - fmt.Println("\tDelayed for:", delayedFor) - } - if event.OrderID == "" { + fmt.Println("ERROR: Received order placed without order_id") return fmt.Errorf("empty order_id") } + fmt.Println("Received order placed:", event.OrderID) + return nil }, ), @@ -126,12 +121,16 @@ func main() { <-router.Running() + i := 0 + for { e := newFakeOrderPlaced() - chance := rand.Intn(10) - if chance < 2 { + i++ + + if i == 10 { e.OrderID = "" + i = 0 } err = eventBus.Publish(context.Background(), e) diff --git a/docs/build.sh b/docs/build.sh index cef7aee2a..16125dfee 100755 --- a/docs/build.sh +++ b/docs/build.sh @@ -49,6 +49,8 @@ else "components/delay/delay.go" "components/delay/publisher.go" + "components/requeuer/requeuer.go" + "components/metrics/builder.go" "components/metrics/http.go" diff --git a/docs/content/advanced/requeuing-after-error.md b/docs/content/advanced/requeuing-after-error.md new file mode 100644 index 000000000..f137dae81 --- /dev/null +++ b/docs/content/advanced/requeuing-after-error.md @@ -0,0 +1,55 @@ ++++ +title = "Requeuing After Error" +description = "How to requeue a message after it fails to process" +weight = -20 +draft = false +bref = "How to requeue a message after it fails to process" ++++ + +When a message fails to process (a nack is sent), it usually blocks other messages on the same topic (within the same consumer group or partition). + +Depending on your setup, it may be useful to requeue the failed message back to the tail of the queue. + +Consider this if: +* You don't care about the order of messages. +* Your system isn't resilient to blocked messages. + +## Requeuer + +The `Requeuer` component is a wrapper on the `Router` that moves messages from one topic to another. + +{{% load-snippet-partial file="src-link/components/requeuer/requeuer.go" first_line_contains="type Config" last_line_contains="}" %}} + +A trivial usage can look like this. It requeues messages from one topic to the same topic after a delay. + +{{< callout "danger" >}} +Using the delay this way is not recommended, as it blocks the entire requeue process for the given time. +{{< /callout >}} + +```go +req, err := requeuer.NewRequeuer(requeuer.Config{ + Subscriber: sub, + SubscribeTopic: "topic", + Publisher: pub, + GeneratePublishTopic: func(params requeuer.GeneratePublishTopicParams) (string, error) { + return "topic", nil + }, + Delay: time.Millisecond * 200, +}, logger) +if err != nil { + return err +} + +err := req.Run(context.Background()) +if err != nil { + return err +} +``` + +A better way to use the `Requeuer` is to combine it with the `Poison` middleware. +The middleware moves messages to a separate "poison" topic. +Then, the requeuer moves them back to the original topic based on the metadata. + +You combine this with a Pub/Sub that supports delayed messages. +See the [full example based on PostgreSQL](https://github.com/ThreeDotsLabs/watermill/blob/master/_examples/real-world-examples/delayed-requeue/main.go). + diff --git a/docs/content/docs/getting-started.md b/docs/content/docs/getting-started.md index 2a645473f..37e1cc13e 100644 --- a/docs/content/docs/getting-started.md +++ b/docs/content/docs/getting-started.md @@ -258,7 +258,6 @@ if err != nil { } ``` - {{< tabs "publishing" >}} {{< tab "Go Channel" "go-channel" >}} diff --git a/docs/content/pubsubs/sql.md b/docs/content/pubsubs/sql.md index 5413c9436..49df08b1e 100644 --- a/docs/content/pubsubs/sql.md +++ b/docs/content/pubsubs/sql.md @@ -30,12 +30,12 @@ go get github.com/ThreeDotsLabs/watermill-sql/v3 ### Characteristics -| Feature | Implements | Note | -|---------------------|------------|-------------------------------------------| -| ConsumerGroups | yes | See `ConsumerGroup` in `SubscriberConfig` | -| ExactlyOnceDelivery | yes* | Just for MySQL implementation | -| GuaranteedOrder | yes | | -| Persistent | yes | | +| Feature | Implements | Note | +|---------------------|------------|-------------------------------------------------------------------------------| +| ConsumerGroups | yes | See `ConsumerGroup` in `SubscriberConfig` (not supported by the queue schema) | +| ExactlyOnceDelivery | yes* | Just for MySQL implementation | +| GuaranteedOrder | yes | | +| Persistent | yes | | ### Schema @@ -83,7 +83,7 @@ constructor. You have to create one publisher for each transaction. Example: {{% load-snippet-partial file="src-link/_examples/real-world-examples/transactional-events/main.go" first_line_contains="func simulateEvents" last_line_contains="return pub.Publish(" padding_after="3" %}} -### Subscribing +## Subscribing To create a subscriber, you need to pass not only proper schema adapter, but also an offsets adapter. @@ -97,9 +97,28 @@ Example: {{% load-snippet-partial file="src-link/watermill-sql/pkg/sql/subscriber.go" first_line_contains="func (s *Subscriber) Subscribe" last_line_contains="func (s *Subscriber) Subscribe" %}} -### Offsets Adapter +## Offsets Adapter The logic for storing offsets of messages is provided by the `OffsetsAdapter`. If your schema uses auto-incremented integer as the row ID, it should work out of the box with default offset adapters. {{% load-snippet-partial file="src-link/watermill-sql/pkg/sql/offsets_adapter.go" first_line_contains="type OffsetsAdapter" %}} + +## Queue + +Instead of the default Pub/Sub schema, you can use the *queue* schema and offsets adapters. + +It's a simpler schema that doesn't support consumer groups. +However, it has other advantages. + +It lets you specify a custom `WHERE` clause for getting the messages. +You can use it to filter messages by some condition in the payload or in the metadata. + +Additionally, you can choose to delete messages from the table after they are acknowledged. +Thanks to this, the table doesn't grow in size with time. + +Currently, this schema is supported only for PostgreSQL. + +{{% load-snippet-partial file="src-link/watermill-sql/pkg/sql/queue_schema_adapter_postgresql.go" first_line_contains="// PostgreSQLQueueSchema" last_line_contains="}" %}} + +{{% load-snippet-partial file="src-link/watermill-sql/pkg/sql/queue_offsets_adapter_postgresql.go" first_line_contains="// PostgreSQLQueueOffsetsAdapter" last_line_contains="}" %}} diff --git a/docs/resources/_gen/images/_hu70523d59fb738bec5c06336403a46531_39940_c0fe83760c1bebd5a39d4ddb7fce622e.webp b/docs/resources/_gen/images/_hu70523d59fb738bec5c06336403a46531_39940_c0fe83760c1bebd5a39d4ddb7fce622e.webp new file mode 100644 index 0000000000000000000000000000000000000000..fa79b73532ce1d996d27e50f4ad73874f1f18969 GIT binary patch literal 16278 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 literal 0 HcmV?d00001 diff --git a/tools/pq/go.mod b/tools/pq/go.mod index 5f2f50e39..4edb60ec2 100644 --- a/tools/pq/go.mod +++ b/tools/pq/go.mod @@ -3,12 +3,13 @@ module github.com/ThreeDotsLabs/watermill/tools/pq go 1.23.0 require ( - github.com/ThreeDotsLabs/watermill v1.4.0-rc.1.0.20241011082756-1cb09cdf7d08 + github.com/ThreeDotsLabs/watermill v1.4.0-rc.2 github.com/charmbracelet/bubbles v0.19.0 github.com/charmbracelet/bubbletea v0.27.1 github.com/charmbracelet/lipgloss v0.13.0 github.com/jmoiron/sqlx v1.4.0 github.com/lib/pq v1.10.9 + github.com/pkg/errors v0.9.1 golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 ) @@ -32,7 +33,6 @@ require ( github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.15.2 // indirect github.com/oklog/ulid v1.3.1 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/sony/gobreaker v1.0.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect @@ -40,5 +40,3 @@ require ( golang.org/x/sys v0.24.0 // indirect golang.org/x/text v0.14.0 // indirect ) - -replace github.com/ThreeDotsLabs/watermill => ../.. diff --git a/tools/pq/go.sum b/tools/pq/go.sum index 9585210df..d10441494 100644 --- a/tools/pq/go.sum +++ b/tools/pq/go.sum @@ -1,5 +1,7 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/ThreeDotsLabs/watermill v1.4.0-rc.2 h1:K62uIAKOkCHTXtAwY+Nj95vyLR0y25UMBsbf/FuWCeQ= +github.com/ThreeDotsLabs/watermill v1.4.0-rc.2/go.mod h1:lBnrLbxOjeMRgcJbv+UiZr8Ylz8RkJ4m6i/VN/Nk+to= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=