{"id":37179601,"url":"https://github.com/alexrudd/gomdb","last_synced_at":"2026-01-14T20:54:04.615Z","repository":{"id":45267698,"uuid":"367669898","full_name":"alexrudd/gomdb","owner":"alexrudd","description":"Message DB Go client","archived":false,"fork":false,"pushed_at":"2022-01-20T08:26:21.000Z","size":72,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-13T12:50:36.745Z","etag":null,"topics":["event-sourcing","event-store","go","message-db","postgres"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexrudd.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}},"created_at":"2021-05-15T15:43:12.000Z","updated_at":"2022-05-19T19:39:42.000Z","dependencies_parsed_at":"2022-09-22T18:44:56.930Z","dependency_job_id":null,"html_url":"https://github.com/alexrudd/gomdb","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/alexrudd/gomdb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexrudd%2Fgomdb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexrudd%2Fgomdb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexrudd%2Fgomdb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexrudd%2Fgomdb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexrudd","download_url":"https://codeload.github.com/alexrudd/gomdb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexrudd%2Fgomdb/sbom","scorecard":{"id":182445,"data":{"date":"2025-08-11","repo":{"name":"github.com/alexrudd/gomdb","commit":"3d1e88e283294165351a723ed47aaef90f1acb3b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/10 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/checks.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/checks.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/alexrudd/gomdb/checks.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/checks.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/alexrudd/gomdb/checks.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/checks.yml:54: update your workflow using https://app.stepsecurity.io/secureworkflow/alexrudd/gomdb/checks.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/checks.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/alexrudd/gomdb/checks.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/checks.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/alexrudd/gomdb/checks.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/checks.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/alexrudd/gomdb/checks.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/checks.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/alexrudd/gomdb/checks.yml/main?enable=pin","Warn: containerImage not pinned by hash: tests/Dockerfile:1: pin your Docker image by updating postgres:13.2-alpine to postgres:13.2-alpine@sha256:c4c7a1585974706b5f72b8ab595e47399b23b2e03d93bbf75c1b0904be1803dc","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 4 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-16T19:06:53.141Z","repository_id":45267698,"created_at":"2025-08-16T19:06:53.141Z","updated_at":"2025-08-16T19:06:53.141Z"},"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":["event-sourcing","event-store","go","message-db","postgres"],"created_at":"2026-01-14T20:54:03.969Z","updated_at":"2026-01-14T20:54:04.604Z","avatar_url":"https://github.com/alexrudd.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Go Message DB Client\n\n[![Checks](https://github.com/alexrudd/gomdb/actions/workflows/checks.yml/badge.svg?event=push)](https://github.com/alexrudd/gomdb/actions/workflows/checks.yml)\n[![PkgGoDev](https://pkg.go.dev/badge/github.com/alexrudd/gomdb)](https://pkg.go.dev/github.com/alexrudd/gomdb)\n\nThis module implements a thin Go wrapper around the [Message DB](https://github.com/message-db/message-db) message store. Message DB is an event store implemented on top of Postgres, ideal for event sourcing applications.\n\nThe client supports all Message DB read and write procedures, choosing to default to their simplest forms and providing configurability through options functions.\n\n## Getting started\n\n```go\n// Open database connection\ndb, err := sql.Open(\"postgres\", \"dbname=message_store sslmode=disable user=message_store\")\nif err != nil {\n    log.Fatalf(\"unexpected error opening db: %s\", err)\n}\ndefer db.Close()\n\n// Set search path for schema\nif _, err := db.Exec(\"SET search_path TO message_store,public;\"); err != nil {\n    log.Fatalf(\"setting search path: %s\", err)\n}\n\n// Create client\nclient := gomdb.NewClient(db)\n\n// Read from stream\nmsgs, err := client.GetStreamMessages(context.Background(), stream)\nif err != nil {\n    log.Fatalf(\"reading from stream: %s\", err)\n}\n\nlog.Println(msgs)\n```\n\nSee the [examples](./tests/examples) or [tests](./tests) directory for more complete examples.\n\n## Subscriptions\n\nSubscriptions are built on top of the `GetStreamMessages` and `GetCategoryMessages` methods and simply poll from the last read version or position.\n\n```go\nsubCtx, cancel := context.WithCancel(context.Background())\ndefer cancel() // cancel will stop the subscription\n\nerr := client.SubscribeToCategory(subCtx, \"user\",\n    func(m *gomdb.Message) { // Message handler\n        log.Printf(\"Received message: %v\", m)\n    },\n    func(live bool) { // Liveness handler\n        if live {\n            log.Print(\"subscription is handling live messages!\")\n        } else {\n            log.Print(\"subscription has fallen behind\")\n        }\n    },\n    func(err error) { // subscription dropped handler\n        if err != nil {\n            log.Fatalf(\"subscription dropped with error: %s\", err)\n        }\n    },\n)\nif err != nil {\n    log.Fatal(err)\n}\n```\n\nDifferent polling strategies can be configured to reduce reads to the database for subscriptions that rarely receive messages. A default strategy can be set in the client, or a subscription specific strategy can be set when creating a subscription.\n\n```go\n// Client configured with exponential backoff as default strategy.\nclient := gomdb.NewClient(\n    db,\n    gomdb.WithDefaultPollingStrategy(\n        gomdb.ExpBackoffPolling(\n            50*time.Millisecond, // minimum polling delay on no messages read\n            5*time.Second,       // maximum polling delay on no messages read\n            2,                   // delay will double for every read that returns no messages\n        ),\n    ),\n)\n\n// Client configured with constant polling interval as default strategy.\nclient = gomdb.NewClient(\n    db,\n    gomdb.WithDefaultPollingStrategy(\n        gomdb.ConstantPolling(100*time.Millisecond), // polling delay on no messages read\n    ),\n)\n\n// Default strategy overidden for specific subscription.\nclient.SubscribeToCategory(subCtx, \"user\",\n    func(m *gomdb.Message) {}, // Message handler\n    func(live bool) {},        // Liveness handler\n    func(err error) {},        // subscription dropped handler\n    gomdb.WithCategoryPollingStrategy(\n        gomdb.ConstantPolling(time.Second)()), // poll every second\n    ),\n)\n```\n\n## Running tests\n\nThe unit tests can be run with `go test`.\n\nSee the [integration tests README](./tests/README.md) for instructions on how to run integration tests.\n\n## Contributing\n\nAll contributions welcome, especially anyone with SQL experience who could tidy up how queries are run and how read errors are handled.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexrudd%2Fgomdb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexrudd%2Fgomdb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexrudd%2Fgomdb/lists"}