{"id":20252635,"url":"https://github.com/streamdal/natty","last_synced_at":"2025-04-10T23:21:47.633Z","repository":{"id":39741890,"uuid":"456393299","full_name":"streamdal/natty","owner":"streamdal","description":"Batteries included NATS Jetstream Go client","archived":false,"fork":false,"pushed_at":"2023-08-17T22:43:32.000Z","size":6192,"stargazers_count":11,"open_issues_count":0,"forks_count":0,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-24T20:11:13.614Z","etag":null,"topics":["golang","golang-library","nats","nats-client"],"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/streamdal.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}},"created_at":"2022-02-07T07:01:16.000Z","updated_at":"2025-03-18T00:14:03.000Z","dependencies_parsed_at":"2023-09-03T03:23:21.542Z","dependency_job_id":null,"html_url":"https://github.com/streamdal/natty","commit_stats":null,"previous_names":["batchcorp/natty"],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamdal%2Fnatty","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamdal%2Fnatty/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamdal%2Fnatty/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamdal%2Fnatty/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/streamdal","download_url":"https://codeload.github.com/streamdal/natty/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248313174,"owners_count":21082812,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["golang","golang-library","nats","nats-client"],"created_at":"2024-11-14T10:17:42.360Z","updated_at":"2025-04-10T23:21:47.608Z","avatar_url":"https://github.com/streamdal.png","language":"Go","readme":"natty\n=====\n[![Go Reference](https://pkg.go.dev/badge/github.com/streamdal/natty.svg)](https://pkg.go.dev/github.com/streamdal/natty)\n[![Go Report Card](https://goreportcard.com/badge/github.com/streamdal/natty)](https://goreportcard.com/report/github.com/streamdal/natty)\n\nAn opinionated, [NATS](https://nats.io) Jetstream client wrapper lib for Go.\n\nUsed by [plumber](https://github.com/streamdal/plumber) and other Batch applications.\n\n## Why\n\nNATS allows you tweak a lot of things - create push or pull streams, durable or\nephemeral consumers and all kinds of other settings.\n\nThe library exposes several, opinionated, quality-of-life functionality such as:\n\n* Simplified publish/consume API *specifically* to be used with NATS-JS\n    * `Consume()` uses ONLY durable consumers (as we want kafka-like behavior)\n* Methods for interacting with key/value store in NATS\n  * Ability to perform safe key `Refresh()`\n* Concurrency / leader election functionality\n\nSee the full interface [here](https://pkg.go.dev/github.com/streamdal/natty#INatty).\n\n## Consume \u0026 Publish\n\nThis library uses ONLY durable consumers and provides a two method API to interact\nwith your NATS deployment:\n\n* `Consume(ctx context.Context, subject string, errorCh chan error, cb func(msg *nats.Msg)) error`\n* `Publish(ctx context.Context, subject string, data []byte) error`\n\nThe `Consume()` will block and has to be cancelled via context. You can also\npass an optional error channel that the lib will write to when the callback func\nruns into an error.\n\n## HasLeader\n\n`natty` provides an easy way to execute a function only if the instance is the\nleader for a given bucket and key.\n\nExample:\n```go\n\nbucketName := \"election-bucket\"\nkeyName := \"election-key\"\n\nn.AsLeader(context.Background(), natty.AsLeaderConfig{\n\tLooper:   director.NewFreeLooper(director.Forever, make(error chan, 1)),\n\tBucket:   bucketName,\n\tKey:      keyName,\n\tNodeName: \"node1\"\n}, func() error {\n\tfmt.Println(\"executed by node 1\")\n})\n\nn.AsLeader(context.Background(), natty.AsLeaderConfig{\n\tLooper:   director.NewFreeLooper(director.Forever, make(error chan, 1)),\n    Bucket:   bucketName, \n    Key:      keyName,\n    NodeName: \"node2\"\n}, func() error {\n    fmt.Println(\"executed by node 2\")\n})\n\n// Only one will be executed\n```\n\n`AsLeader` uses NATS k/v store to facilitate leader election.\n\n### Election Logic\n\nDuring first execution, all instances running `AsLeader()` on the same bucket \nand key will attempt to `Create()` the leader key - only one will succeed as \n`Create()` will error if a key already exists.\n\nOn subsequent iterations, each `AsLeader()` will first check if it is the leader\nby reading the key in the bucket. If it is the leader, it will `Put()` the \ncfg.Key with contents set to cfg.NodeName - the `Put()` will NOT error if the \nkey already exists.\n\nIf the current leader is unable to `Put()` - it will try again next time until\nit either succeeds or the key is TTL'd by the bucket policy.\n\nWhen the bucket TTL is reached, the key will be deleted by NATS at which point,\none of the `AsLeader()` instances `Create()` call will succeed and they will\nbecome the current leader.\n\n## TLS NATS\n\nThe NATS server started via `docker-compose` is configured to use TLS (with keys\nand certs located in `./assets/*`).\n\nWe are doing NATS w/ TLS purely to ensure that the library will work with it.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstreamdal%2Fnatty","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstreamdal%2Fnatty","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstreamdal%2Fnatty/lists"}