{"id":37178838,"url":"https://github.com/igmagollo/undine","last_synced_at":"2026-01-14T20:50:20.570Z","repository":{"id":212983031,"uuid":"732418581","full_name":"igmagollo/undine","owner":"igmagollo","description":"An opinionated library that combines Ent and Watermill into a set of powerful utilities to transactionally handle events.","archived":false,"fork":false,"pushed_at":"2024-01-23T15:18:40.000Z","size":108,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-01-23T16:34:34.004Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/igmagollo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-12-16T16:01:12.000Z","updated_at":"2024-01-23T15:36:55.000Z","dependencies_parsed_at":"2023-12-17T19:22:18.901Z","dependency_job_id":"902b69f5-65f1-4a90-b2fb-5c2fbd233cb4","html_url":"https://github.com/igmagollo/undine","commit_stats":null,"previous_names":["igmagollo/undine"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/igmagollo/undine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igmagollo%2Fundine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igmagollo%2Fundine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igmagollo%2Fundine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igmagollo%2Fundine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/igmagollo","download_url":"https://codeload.github.com/igmagollo/undine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igmagollo%2Fundine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28434500,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T18:57:19.464Z","status":"ssl_error","status_checked_at":"2026-01-14T18:52:48.501Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-14T20:50:19.760Z","updated_at":"2026-01-14T20:50:20.557Z","avatar_url":"https://github.com/igmagollo.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# undine\n\nAn opinionated library that combines Ent and Watermill into a set of powerful utilities for transactionally handle events.\n\n[Ent](https://entgo.io/) is a entity library that generates strongly typed query builders based on the schema. It is simple and its benefits easily overcome the fact that you need to learn how it works instead of just writing raw SQL. It also offers extensions capabilities were you can leverage the schema and generate your own code, e.g. Proto files, OpenAPI specs or GraphQL schemas matching your database schema.\n\n[Watermill](https://watermill.io/) is a library for building event-driven applications. It offers Publisher and Subscriber interfaces and implementations of them for a lot of [message brokers](https://watermill.io/pubsubs/). It has a powerfull and flexible router and offers plenty of other features that makes our lives a lot easier.\n\nThis package is meant to combine the watermill with Ent in a way that we can use the Outbox pattern (forwarder component) and a deduplication easily\n\n# What this library offers\n\n- [x] Client exporting WithTx utility function\n- [x] Outbox pattern (with watermill forwarder over Ent)\n- [x] Deduplication\n- [x] All glue code needed generated inside Ent using this Extension\n\n# How to use\n\nFirst, add the extension to the entc command:\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\n\tundine \"github.com/igmagollo/undine/pkg/v1\"\n\n\t\"entgo.io/ent/entc\"\n\t\"entgo.io/ent/entc/gen\"\n)\n\nfunc main() {\n\terr := entc.Generate(\"./schema\", \u0026gen.Config{}, entc.Extensions(\n\t\tundine.Extension{},\n\t))\n\tif err != nil {\n\t\tlog.Fatalf(\"running ent codegen: %v\", err)\n\t}\n}\n\n```\n\nNow we need to initialize the database passing some dependencies as follows:\n```go\nclient, err := ent.Open(\"postgres\", \"host=127.0.0.1 port=5432 user=postgres dbname=postgres password=postgres sslmode=disable\",\n\t\tent.DeduplicatorSchemaAdapter(\u0026undine.DeduplicatorPostgresSchemaAdapter{}), // Deduplicator sql adapter\n\t\tent.WatermillLogger(logger),\n\t\tent.Publisher(pubsub), // outside publisher so forwarder can forward messages\n\t\tent.OutboxOffsetsAdapter(\u0026sql.DefaultPostgreSQLOffsetsAdapter{}), // outbox sql adapter\n\t\tent.OutboxSchemaAdapter(\u0026sql.DefaultPostgreSQLSchema{}), // outbox sql adapter\n)\n```\n\nThen everything that we need is inside `ent.Client` and `ent.Tx` structs:\n```go\nforwarder := client.Forwarder(consumerGroup)\n\ngo func() {\n  if err := forwarder.Run(context.Background()); err != nil {\n    panic(err)\n  }\n}()\n\n...\n\nerr := client.WithTx(ctx, func(ctx context.Context) error {\n      tx := ent.TxFromContext(ctx)\n      deduplicator := tx.Deduplicator()\n      outboxPublisher, err := tx.OutboxPublisher()\n\n      ...\n\n      err = deduplicator.Deduplicate(ctx, topic, msgID)\n\n      ...\n\n      err = outboxPublisher.Publish(topic, msg)\n\n      ...\n})\n\nif undine.IsDuplicationError(err) {\n  ...\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figmagollo%2Fundine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Figmagollo%2Fundine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figmagollo%2Fundine/lists"}