{"id":40922249,"url":"https://github.com/mission-liao/dingo","last_synced_at":"2026-01-22T03:35:11.677Z","repository":{"id":46160387,"uuid":"42429363","full_name":"mission-liao/dingo","owner":"mission-liao","description":"An easy-to-use, distributed, extensible task/job queue framework for #golang","archived":false,"fork":false,"pushed_at":"2021-11-10T08:38:17.000Z","size":464,"stargazers_count":294,"open_issues_count":9,"forks_count":15,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-06-20T08:18:16.109Z","etag":null,"topics":["golang","task-queue","workers"],"latest_commit_sha":null,"homepage":"http://godoc.org/github.com/mission-liao/dingo","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/mission-liao.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":"2015-09-14T05:41:19.000Z","updated_at":"2024-05-26T06:39:30.000Z","dependencies_parsed_at":"2022-09-24T17:32:23.884Z","dependency_job_id":null,"html_url":"https://github.com/mission-liao/dingo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mission-liao/dingo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mission-liao%2Fdingo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mission-liao%2Fdingo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mission-liao%2Fdingo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mission-liao%2Fdingo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mission-liao","download_url":"https://codeload.github.com/mission-liao/dingo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mission-liao%2Fdingo/sbom","scorecard":{"id":649832,"data":{"date":"2025-08-11","repo":{"name":"github.com/mission-liao/dingo","commit":"561878de3d1e73632aca68d0116153f3a253c186"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Code-Review","score":1,"reason":"Found 3/28 approved changesets -- score normalized to 1","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":"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":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"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":"Dangerous-Workflow","score":-1,"reason":"no workflows found","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":"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":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"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":"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":"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":"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"}},{"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: 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":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"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 5 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"}}]},"last_synced_at":"2025-08-21T13:13:41.405Z","repository_id":46160387,"created_at":"2025-08-21T13:13:41.405Z","updated_at":"2025-08-21T13:13:41.405Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28652865,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"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":["golang","task-queue","workers"],"created_at":"2026-01-22T03:35:11.012Z","updated_at":"2026-01-22T03:35:11.665Z","avatar_url":"https://github.com/mission-liao.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dingo\r\n\r\n[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/mission-liao/dingo) [![Build Status](https://travis-ci.org/mission-liao/dingo.svg)](https://travis-ci.org/mission-liao/dingo) [![Coverage Status](https://coveralls.io/repos/mission-liao/dingo/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/mission-liao/dingo?branch=master)\r\n\r\nI initiated this project after [machinery](https://github.com/RichardKnop/machinery), which is a great library and tends to provide a replacement of [Celery](http://www.celeryproject.org/) in #golang. The reasons to create (yet) another task library are:\r\n- To make sending tasks as easy as possible\r\n- Await and receive reports through channels. (_channel_ is a natural way to represent asynchronous results)\r\n- I want to get familiar with those concepts of #golang: **interface**, **routine**, **channel**, and a distributed task framework is a good topic for practice, :)\r\n\r\nOne important concept I learned from [Celery](http://www.celeryproject.org/) and inherited in __Dingo__ is that __Caller__ and __Worker__ could share the same codebase.\r\n\u003e When you send a task message in Celery, that message will not contain any source code, but only the name of the task you want to execute. This works similarly to how host names work on the internet: every worker maintains a mapping of task names to their actual functions, called the task registry.\r\n\r\nBelow is a quicklink to go through this README:\r\n- [Quick Demo](README.md#quick-demo)\r\n- [Features](README.md#features)\r\n  - [Invoking Worker Functions with Arbitary Signatures](README.md#invoking-worker-functions-with-arbitary-signatures)\r\n  - [Stateful Worker Functions](README.md#stateful-worker-functions)\r\n  - [Two Way Binding with Worker Functions](README.md##two-way-binding-with-worker-functions)\r\n  - [A Distributed Task Framework with Local Mode](README.md#a-distributed-task-framework-with-local-mode)\r\n  - [Customizable](README.md#customizable)\r\n  - Supported Database Adaptor: [AMQP](amqp/README.md), [Redis](redis/README.md)\r\n  - Supported Golang Version: 1.4, 1.5, 1.6\r\n- [Guide](docs/guide/README.md) \r\n- [Benchmark](docs/benchmark.md)\r\n\r\n## Quick Demo\r\nHere is a quick demo of this project in local mode as a background job pool:\r\n```go\r\npackage main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"github.com/mission-liao/dingo\"\r\n)\r\n\r\nfunc main() {\r\n\t// initiate a local app\r\n\tapp, err := dingo.NewApp(\"local\", nil)\r\n\tif err != nil {\r\n\t\treturn\r\n\t}\r\n\t// register a worker function\r\n\terr = app.Register(\"add\", func(a int, b int) int {\r\n\t\treturn a + b\r\n\t})\r\n\tif err != nil {\r\n\t\treturn\r\n\t}\r\n\r\n\t// allocate workers for that function: 2 workers, sharing 1 report channel.\r\n\t_, err = app.Allocate(\"add\", 2, 1)\r\n\r\n\t// wrap the report channel with dingo.Result\r\n\tresult := dingo.NewResult(app.Call(\"add\", dingo.DefaultOption(), 2, 3))\r\n\terr = result.Wait(0)\r\n\tif err != nil {\r\n\t\treturn\r\n\t}\r\n    // set callback like promise in javascript\r\n\tresult.OnOK(func(sum int) {\r\n\t\tfmt.Printf(\"result is: %v\\n\", sum)\r\n\t})\r\n\r\n\t// release resource\r\n\terr = app.Close()\r\n\tif err != nil {\r\n\t\treturn\r\n\t}\r\n}\r\n```\r\n\r\n## Features\r\n\r\n### Invoking Worker Functions with Arbitary Signatures\r\n\u003e (Almost) ANY Function Can Be Your Dingo\r\n\r\nThese functions can be used as __worker functions__ by dingo:\r\n```go\r\ntype Person struct {\r\n  ID int\r\n  Name string\r\n}\r\nfunc NewEmployee(p *Person, age int) (failed bool) { ... } // struct, OK\r\nfunc GetEmployees(age int) (employees map[string]*Person) { ... } // map of struct, OK\r\nfunc DeleteEmployees(names []string) (count int) { ... } // slice, OK\r\nfunc DoNothing () { ... } // OK\r\n```\r\n\r\nIdealy, you don't have to rewrite your function to fit any specific signature, it's piece of cake to adapt a function to __Dingo__.\r\n\r\nBelow is to explain why some types can't be supported by __Dingo__: The most compatible exchange format is []byte, to marshall in/out your parameters to []byte, we rely these builtin encoders:\r\n - encoding/json\r\n - encoding/gob\r\n\r\nType info are deduced from the signatures of worker functions you register. With those type info, parameters are unmarshalled from []byte to cloeset type. A __type correction__ procedure would be applied on those parameters before invoking.\r\n\r\nObviously, it's hard (not impossible) to handle all types in #golang, these are unsupported by __Dingo__ as far as I know:\r\n - __interface__: unmarshalling requires concrete types. (so __error__ can be marshalled, but can't be un-marshalled)\r\n - __chan__: haven't tried yet\r\n - __private field in struct__: they are ignore by json/gob, but it's still possible to support them by providing customized marshaller and invoker. (please search 'ExampleCustomMarshaller' for details)\r\n\r\n### Stateful Worker Functions\r\n\u003e Dingo Remembers things\r\n\r\nWanna create a worker function with __states__? Two ways to did this in __Dingo__:\r\n - The [reflect](https://golang.org/pkg/reflect/) package allow us to invoke a method of struct, so you can initiate an instance of your struct to hold every global and provide its method as worker functions.\r\n - create a closure to enclose states or globals\r\n\r\nRefer to [Stateful Worker Functions](docs/guide/stateful_worker_function.md) for more details.\r\n \r\n### Two Way Binding with Worker Functions\r\n\u003e Throwing and Catching with Your Dingo\r\n\r\nBesides sending arguments, return values from worker functions can also be accessed. Every time you initiate a task, you will get a report channel.\r\n```go\r\nreports, err := app.Call(\"yourTask\", nil, arg1, arg2 ...)\r\n\r\n// synchronous waiting\r\nr := \u003c-reports\r\n\r\n// asynchronous waiting\r\ngo func () {\r\n  r := \u003c-reports\r\n}()\r\n\r\n// access the return values\r\nif r.OK() {\r\n  var ret []interface{} = r.Return()\r\n  ret[0].(int) // by type assertion\r\n}\r\n```\r\nOr using:\r\n - [dingo.Result](https://godoc.org/github.com/mission-liao/dingo#Result)\r\n\r\n### A Distributed Task Framework with Local Mode\r\n\u003e Dingo @Home, or Anywhere\r\n\r\nYou would prefer a small, local worker pool at early development stage, and transfer to a distributed one when stepping in production. In dingo, there is nothing much to do for transfering (besides debugging, :( )\r\n\r\nYou've seen a demo for local mode, and it's easy to make it distributed by attaching corresponding components at caller-side and worker-side. A demo: [caller](https://godoc.org/github.com/mission-liao/dingo#example-App-Use-Caller) and [worker](https://godoc.org/github.com/mission-liao/dingo#ex-App-Use-Worker).\r\n\r\nIn short, at __Caller__ side, you need to:\r\n - register worker functions for tasks\r\n - config __default-option__, __id-maker__, __marshaller__ for tasks if needed.\r\n - attach __Producer__, __Store__\r\n\r\nAnd at __Worker__ side, you need to:\r\n - register the same worker function as the one on __Caller__ side for tasks\r\n - config __marshaller__ for tasks if needed, the marshaller used for __Caller__ and __Worker__ should be sync.\r\n - attach __Consumer__ (or __NamedConsumer__), __Reporter__\r\n - allocate worker routines\r\n\r\n### Customizable\r\n\u003e Personalize Your Dingo\r\n\r\nMany core behaviors can be customized:\r\n - Generation of ID for new tasks: [IDMaker](https://godoc.org/github.com/mission-liao/dingo#IDMaker)\r\n - Parameter Marshalling: [Marshaller](https://godoc.org/github.com/mission-liao/dingo#Marshaller)\r\n - Worker Function Invoking: [Invoker](https://godoc.org/github.com/mission-liao/dingo#Invoker)\r\n - Task Publishing/Consuming: [Producer](https://godoc.org/github.com/mission-liao/dingo#Producer)/[Consumer](https://godoc.org/github.com/mission-liao/dingo#Consumer)/[NamedConsumer](https://godoc.org/github.com/mission-liao/dingo#NamedConsumer)\r\n - Report Publishing/Consuming: [Reporter](https://godoc.org/github.com/mission-liao/dingo#Reporter)/[Store](https://godoc.org/github.com/mission-liao/dingo#Store)\r\n\r\n### Development Environment Setup\r\n\r\nThere is no dependency manager in this project, you need to install them by yourself.\r\n```bash\r\ngo get github.com/streadway/amqp\r\ngo get github.com/garyburd/redigo/redis\r\ngo get github.com/stretchr/testify\r\ngo get github.com/satori/go.uuid\r\n```\r\n\r\nInstall [Redis](http://redis.io/download) and [Rabbitmq](https://www.rabbitmq.com/download.html), then unittest @ the root folder of dingo\r\n```bash\r\ngo test -v ./...\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmission-liao%2Fdingo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmission-liao%2Fdingo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmission-liao%2Fdingo/lists"}