{"id":19429200,"url":"https://github.com/ehsaniara/gointerlock","last_synced_at":"2025-07-11T15:37:51.012Z","repository":{"id":39666818,"uuid":"391251279","full_name":"ehsaniara/gointerlock","owner":"ehsaniara","description":"Centralized Lock for Distributed Scheduler/Task ⏱️ for Go (Supports Redis, DynamoDb, Postgres🔒).","archived":false,"fork":false,"pushed_at":"2024-10-05T23:13:54.000Z","size":724,"stargazers_count":46,"open_issues_count":1,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-05T20:06:50.476Z","etag":null,"topics":["distributed-locking","distributed-systems","dynamodb","go","golang","redis","redis-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/ehsaniara.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-31T04:09:28.000Z","updated_at":"2024-12-11T11:36:33.000Z","dependencies_parsed_at":"2024-12-23T10:28:47.758Z","dependency_job_id":"47ad56e5-a9f9-4385-919e-ab83c14809f8","html_url":"https://github.com/ehsaniara/gointerlock","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/ehsaniara/gointerlock","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehsaniara%2Fgointerlock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehsaniara%2Fgointerlock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehsaniara%2Fgointerlock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehsaniara%2Fgointerlock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ehsaniara","download_url":"https://codeload.github.com/ehsaniara/gointerlock/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehsaniara%2Fgointerlock/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264841967,"owners_count":23671907,"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":["distributed-locking","distributed-systems","dynamodb","go","golang","redis","redis-client"],"created_at":"2024-11-10T14:18:23.749Z","updated_at":"2025-07-11T15:37:50.959Z","avatar_url":"https://github.com/ehsaniara.png","language":"Go","readme":"# goInterLock \n![Go Interval Lock](material/gointerlock_bg.png)\n\n_known as: ⏰ Interval (Cron / Job / Task / Scheduler) Go Centralized Lock ⏱️_\n\n## Go Interval job/task , with centralized Lock for Distributed Systems\n\n`goInterLock` is go job/task scheduler with centralized locking mechanism. In distributed system locking is preventing task been executed in every instant that has the scheduler, \n\n\u003e  **_Note:_** Kubernetes has the Lease object, which you can use to implement the `Leader election`. [Here is a working example of using kubernetes Lease API](K8sLease.md)  \n\n**For example:** if your application has a task of calling some external APIs or doing some DB querying every 10 minutes, the lock prevents the process been run in every instance of that application, and you ended up running that task multiple time every 10 minutes.\n\nQuick Start\n\n```shell\ngo get github.com/ehsaniara/gointerlock\n```\n\nSupported Lock\n- [Redis](#redis)\n- [AWS DynamoDB](#aws-dynamodb)\n- Postgres DB\n\n# Local Scheduler (Single App)\n\n(Interval every 2 seconds)\n\n```go\nvar job = gointerlock.GoInterval{\n    Interval: 2 * time.Second,\n    Arg:      myJob,\n}\nerr := job.Run(ctx)\nif err != nil {\n        log.Fatalf(\"Error: %s\", err)\n}\n```\n\n### Examples\n[**Basic Local Task:**](example/basicLocal/main.go) Simple Task Interval (Single App).\n\n[**Application Cache:**](./example/applicationCache/main.go) An example of periodically cached value update on http server.\n\n------\n# Distributed Mode (Scaled Up)\n\n## Redis (Recommended)\n\n### Existing Redis Connection\nyou should already configure your Redis connection and pass it into the `GoInterLock`. Also make sure you are giving the\nunique name per job\n\nStep 1: configure redis connection `redisConnection.Rdb` from the existing application and pass it into the Job. for example:\n```go\nvar redisConnector = redis.NewClient(\u0026redis.Options{\n    Addr:     \"localhost:6379\",\n    Password: \"myRedisPassword\", \n    DB:       0,               \n})\n```\nStep 2: Pass the redis connection into the `GoInterval`\n\n```go\nvar job = gointerlock.GoInterval{\n    Interval: 2 * time.Second,\n    Arg:      myJob,\n    Name:     \"MyTestJob\",\n    RedisConnector: redisConnector,\n}\nerr := jobTicker.Run(ctx)\nif err != nil {\n    log.Fatalf(\"Error: %s\", err)\n}\n```\n\nin both examples `myJob` is your function, for example:\n\n```go\nfunc myJob() {\n\tfmt.Println(time.Now(), \" - called\")\n}\n```\n\u003e Currently `GoInterLock` does not support any argument for the job function\n\n### Built in Redis Connector\n\nanother way is to use an existing redis connection:\n\n```go\nvar job = gointerlock.GoInterval{\n    Name:          \"MyTestJob\",\n    Interval:      2 * time.Second,\n    Arg:           myJob,\n    RedisHost:     \"localhost:6379\",\n    RedisPassword: \"myRedisPassword\", //if no pass leave it as \"\"\n}\nerr := job.Run(context.Background())\nif err != nil {\n    log.Fatalf(\"Error: %s\", err)\n}\n```\n\n##### GoInterLock is using [go-redis](https://github.com/go-redis/redis) for Redis Connection.\n\n\n\n### Examples\n\n[**Basic Distributed Task:**](example/redis/basic/main.go) Simple Task Interval with Redis Lock.\n\n-----\n\n## AWS DynamoDb\n\n### Basic Config (Local Environment)\nThis ia sample of local DynamoDb (Docker) for your local test. \n```go\nvar job = gointerlock.GoInterval{\n    Name:                       \"MyTestJob\",\n    Interval:                   2 * time.Second,\n    Arg:                        myJob,\n    LockVendor:                 gointerlock.AwsDynamoDbLock,\n    AwsDynamoDbRegion:          \"us-east-1\",\n    AwsDynamoDbEndpoint:        \"http://127.0.0.1:8000\",\n    AwsDynamoDbSecretAccessKey: \"dummy\",\n    AwsDynamoDbAccessKeyID:     \"dummy\",\n}\nerr := job.Run(cnx)\nif err != nil {\n    log.Fatalf(\"Error: %s\", err)\n}\n```\ntask:\n```go\nfunc myJob() {\n\tfmt.Println(time.Now(), \" - called\")\n}\n```\n\u003e You can get the docker-compose file from [AWS DynamoDB Docker compose](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html) , also avalble from: [docker-compose.yml](./example/awsDynamoDb/docker-compose.yml).\n\n### Using AWS Profile\n\n`goInterLock` will get credentials from the AWS profile\n\n```go\nvar job = gointerlock.GoInterval{\n    Name:                       \"MyTestJob\",\n    Interval:                   2 * time.Second,\n    Arg:                        myJob,\n}\nerr := job.Run(cnx)\nif err != nil {\n    log.Fatalf(\"Error: %s\", err)\n}\n```\n### Examples\n\n[**Basic Distributed Task:**](example/awsDynamoDb/main.go) Simple Task Interval with DynamoDb Lock.\n\n\n\n# :four_leaf_clover: Centralized lock for the Distributed Systems (No Timer/Scheduler)\n\n```go\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/go-redis/redis/v8\"\n)\n\ntype DistributedLock interface {\n\tLock(ctx context.Context, lockName string, maxLockingDuration time.Duration) bool\n\tUnLock(ctx context.Context, lockName string)\n}\n\nfunc NewDistributedLock(rdb *redis.Client) DistributedLock {\n\treturn \u0026distributedLock{\n\t\trdb: rdb,\n\t}\n}\n\ntype distributedLock struct {\n\trdb *redis.Client\n}\n\n// Lock return TRUE when successfully locked, return FALSE if it's already been locked by others\nfunc (d distributedLock) Lock(ctx context.Context, lockName string, maxLockingDuration time.Duration) bool {\n\tkey := fmt.Sprintf(\"lock_%s\", lockName)\n\t//check if it's already locked\n\titer := d.rdb.Scan(ctx, 0, key, 0).Iterator()\n\tfor iter.Next(ctx) {\n\t\t//exit if lock exist\n\t\treturn false\n\t}\n\t//then lock it then\n\td.rdb.Set(ctx, key, []byte(\"true\"), maxLockingDuration)\n\treturn true\n}\n\nfunc (d distributedLock) UnLock(ctx context.Context, lockName string) {\n\tkey := fmt.Sprintf(\"lock_%s\", lockName)\n\t//remove the lock\n\td.rdb.Del(ctx, key)\n}\n\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fehsaniara%2Fgointerlock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fehsaniara%2Fgointerlock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fehsaniara%2Fgointerlock/lists"}