{"id":19974575,"url":"https://github.com/twooster/glock","last_synced_at":"2026-06-09T11:31:40.683Z","repository":{"id":142825068,"uuid":"191450644","full_name":"twooster/glock","owner":"twooster","description":"Golang distributed locks using DynamoDB","archived":false,"fork":false,"pushed_at":"2019-06-11T21:36:41.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2023-03-15T06:35:17.285Z","etag":null,"topics":["distributed-lock","dynamodb","go"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/twooster.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-11T21:14:29.000Z","updated_at":"2024-06-19T07:38:07.852Z","dependencies_parsed_at":"2023-04-05T05:59:39.736Z","dependency_job_id":null,"html_url":"https://github.com/twooster/glock","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"purl":"pkg:github/twooster/glock","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twooster%2Fglock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twooster%2Fglock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twooster%2Fglock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twooster%2Fglock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/twooster","download_url":"https://codeload.github.com/twooster/glock/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twooster%2Fglock/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34105565,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["distributed-lock","dynamodb","go"],"created_at":"2024-11-13T03:15:27.328Z","updated_at":"2026-06-09T11:31:40.667Z","avatar_url":"https://github.com/twooster.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Glock\n\n## What is it?\n\nIt's sketches of a simple distributed locking system that relies upon\nDynamoDB.\n\n## Why?\n\nSometimes you want distributed locks.\n\n## How?\n\nWell, first, you probably want to turn this into production ready code.\nProbably by hiring someone who actually knows how to write good Go code.\n\nAnyway.\n\n### Acquire A Lock\n\n`POST/PUT`\n`http://localhost:12345/locks/\u003clock name\u003e?nonce=\u003cnonce-up-to-64-chars\u003e`\n\nThis will acquire the lock `\u003clock name\u003e`. You must provide a nonce so that\nyou can re-acquire the lock without waiting for its expiration, allowing for\nidempotent acquisitions.\n\nYou will receive back some JSON:\n\n```\n{\n    \"acquireTime\": \"2019-06-11T22:57:31.404462301+02:00\",\n    \"expireTime\": \"2019-06-11T22:58:01.404462301+02:00\",\n    \"fence\": 13,\n    \"body\": \"some contents\"\n}\n```\n\nThe \"body\" is a value you can set so that you can also resume a\nprocess that was stopped in the middle. Probably useful for\ntwo-phase commit or some business like that.\n\nThe \"fence\" is used for the commands below, to prevent competing\nlock holders from doing the wrong thing. Note, that if you re-acquire\na lock by using the same nonce, the fence value will be incremented.\n\n\n### Heartbeat A Lock\n\n`POST/PUT`\n`http://localhost:12345/locks/\u003clock name\u003e/\u003cfence\u003e/heartbeat`\n\nThis will extend your expiration time.  If the value of `fence` is wrong, or\nif the lock has expired, you will receive an error.\n\n### Update A Lock's Value\n\n`POST/PUT`\n`http://localhost:12345/locks/\u003clock name\u003e/\u003cfence\u003e`\n\nThis will update the value of the \"body\" field of the lock, while also\nheartbeating the lock. Put the desired value in the request body. Please use\nstrings so that JSON doesn't barf. There's not much checking going on here yet.\n\nIf the value of `fence` is wrong, or the lock has expired,\nyou will receive an error.\n\nWhy is this here?\n\nWell, it might be a design mistake. If you're running attempting to\nprovide mutual exclusion _and_ disaster recovery if a distributed\nprocess fails, then it's nice to know what your last state was.\nSee discussion below.\n\n### Release A Lock\n\n`DELETE`\n`http://localhost:12345/locks/\u003clock name\u003e/\u003cfence\u003e`\n\nIdempotent.\n\nThis method will always succeed so long as there's no database\nfailures. If you have the right fence number, it will set the\nexpiration time to epoch, otherwise it will just return 200\nwithout doing anything.\n\n\n## Why Have Lock Values?\n\nSo, the `value` thing. There are a few reasons you might want a distributed\nlock. But one pretty important one is running some form of asynchronous\nprocess that could die in the middle. My use case was thinking about\nan asynchronous process that's doing two-phase-commits across two\ndatabases.\n\nHow might this assist?\n\nWell, something like:\n\n```\nDB1             DB2             LOCK\n                                Acquire job.123\n                                If \"body\" is empty, continue\n\nBEGIN           BEGIN\n...work         ...work\n                                Update value: \"rollback\"\n                PREPARE COMMIT\nPREPARE COMMIT\n                                Update value: \"rollforward\"\n                COMMIT PREPARED\nCOMMIT PREPARED\n                                Update value: \"\"\n```\n\nSo the basic concept is you can keep track of the state of the\nasync job. In case your process is killed, you know where you\nneed to pick up again.\n\nThis might be a completely unnecessary addition, but it simplifies\ncertain things. Dunno.\n\n\n## TODO\n\n* [ ] Tests\n* [ ] Better value checking around `value`s\n* [ ] Sweeper to clean up really old locks\n* [ ] Actual configuration via env vars\n* [ ] Actual production DynamoDB settings\n* [ ] Namespaces? Enforced lock name characters?\n* [ ] Customizable lease durations (per req)?\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwooster%2Fglock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftwooster%2Fglock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwooster%2Fglock/lists"}