{"id":13413111,"url":"https://github.com/Jeffail/tunny","last_synced_at":"2025-03-14T19:31:21.109Z","repository":{"id":15635791,"uuid":"18372716","full_name":"Jeffail/tunny","owner":"Jeffail","description":"A goroutine pool for Go","archived":false,"fork":false,"pushed_at":"2023-03-09T21:15:22.000Z","size":170,"stargazers_count":3886,"open_issues_count":8,"forks_count":307,"subscribers_count":71,"default_branch":"master","last_synced_at":"2024-10-29T15:34:20.090Z","etag":null,"topics":["go","golang","goroutine-pool","workers"],"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/Jeffail.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"Jeffail"}},"created_at":"2014-04-02T16:14:58.000Z","updated_at":"2024-10-27T23:28:46.000Z","dependencies_parsed_at":"2024-01-08T15:34:34.830Z","dependency_job_id":null,"html_url":"https://github.com/Jeffail/tunny","commit_stats":{"total_commits":45,"total_committers":9,"mean_commits":5.0,"dds":0.6888888888888889,"last_synced_commit":"a274c3ce48a6dc4f7b5fb5b8eaefbbd9e23574b9"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jeffail%2Ftunny","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jeffail%2Ftunny/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jeffail%2Ftunny/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jeffail%2Ftunny/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jeffail","download_url":"https://codeload.github.com/Jeffail/tunny/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243392317,"owners_count":20283563,"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":["go","golang","goroutine-pool","workers"],"created_at":"2024-07-30T20:01:33.608Z","updated_at":"2025-03-14T19:31:21.086Z","avatar_url":"https://github.com/Jeffail.png","language":"Go","readme":"![Tunny](tunny_logo.png \"Tunny\")\n\n[![godoc for Jeffail/tunny][1]][2]\n[![goreportcard for Jeffail/tunny][3]][4]\n\nTunny is a Golang library for spawning and managing a goroutine pool, allowing\nyou to limit work coming from any number of goroutines with a synchronous API.\n\nA fixed goroutine pool is helpful when you have work coming from an arbitrary\nnumber of asynchronous sources, but a limited capacity for parallel processing.\nFor example, when processing jobs from HTTP requests that are CPU heavy you can\ncreate a pool with a size that matches your CPU count.\n\n## Install\n\n``` sh\ngo get github.com/Jeffail/tunny\n```\n\nOr, using dep:\n\n``` sh\ndep ensure -add github.com/Jeffail/tunny\n```\n\n## Use\n\nFor most cases your heavy work can be expressed in a simple `func()`, where you\ncan use `NewFunc`. Let's see how this looks using our HTTP requests to CPU count\nexample:\n\n``` go\npackage main\n\nimport (\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"runtime\"\n\n\t\"github.com/Jeffail/tunny\"\n)\n\nfunc main() {\n\tnumCPUs := runtime.NumCPU()\n\n\tpool := tunny.NewFunc(numCPUs, func(payload interface{}) interface{} {\n\t\tvar result []byte\n\n\t\t// TODO: Something CPU heavy with payload\n\n\t\treturn result\n\t})\n\tdefer pool.Close()\n\n\thttp.HandleFunc(\"/work\", func(w http.ResponseWriter, r *http.Request) {\n\t\tinput, err := ioutil.ReadAll(r.Body)\n\t\tif err != nil {\n\t\t\thttp.Error(w, \"Internal error\", http.StatusInternalServerError)\n\t\t}\n\t\tdefer r.Body.Close()\n\n\t\t// Funnel this work into our pool. This call is synchronous and will\n\t\t// block until the job is completed.\n\t\tresult := pool.Process(input)\n\n\t\tw.Write(result.([]byte))\n\t})\n\n\thttp.ListenAndServe(\":8080\", nil)\n}\n```\n\nTunny also supports timeouts. You can replace the `Process` call above to the\nfollowing:\n\n``` go\nresult, err := pool.ProcessTimed(input, time.Second*5)\nif err == tunny.ErrJobTimedOut {\n\thttp.Error(w, \"Request timed out\", http.StatusRequestTimeout)\n}\n```\n\nYou can also use the context from the request (or any other context) to handle timeouts and deadlines. Simply replace the `Process` call to the following:\n\n``` go\nresult, err := pool.ProcessCtx(r.Context(), input)\nif err == context.DeadlineExceeded {\n\thttp.Error(w, \"Request timed out\", http.StatusRequestTimeout)\n}\n```\n\n## Changing Pool Size\n\nThe size of a Tunny pool can be changed at any time with `SetSize(int)`:\n\n``` go\npool.SetSize(10) // 10 goroutines\npool.SetSize(100) // 100 goroutines\n```\n\nThis is safe to perform from any goroutine even if others are still processing.\n\n## Goroutines With State\n\nSometimes each goroutine within a Tunny pool will require its own managed state.\nIn this case you should implement [`tunny.Worker`][tunny-worker], which includes\ncalls for terminating, interrupting (in case a job times out and is no longer\nneeded) and blocking the next job allocation until a condition is met.\n\nWhen creating a pool using `Worker` types you will need to provide a constructor\nfunction for spawning your custom implementation:\n\n``` go\npool := tunny.New(poolSize, func() Worker {\n\t// TODO: Any per-goroutine state allocation here.\n\treturn newCustomWorker()\n})\n```\n\nThis allows Tunny to create and destroy `Worker` types cleanly when the pool\nsize is changed.\n\n## Ordering\n\nBacklogged jobs are not guaranteed to be processed in order. Due to the current\nimplementation of channels and select blocks a stack of backlogged jobs will be\nprocessed as a FIFO queue. However, this behaviour is not part of the spec and\nshould not be relied upon.\n\n[1]: https://godoc.org/github.com/Jeffail/tunny?status.svg\n[2]: http://godoc.org/github.com/Jeffail/tunny\n[3]: https://goreportcard.com/badge/github.com/Jeffail/tunny\n[4]: https://goreportcard.com/report/Jeffail/tunny\n[tunny-worker]: https://godoc.org/github.com/Jeffail/tunny#Worker\n","funding_links":["https://github.com/sponsors/Jeffail"],"categories":["Misc","Go","开源类库","Goroutines","Open source library","協程","\u003cspan id=\"协程-Coroutines\"\u003e协程 Coroutines\u003c/span\u003e","Goroutines `goroutines的管理和使用`","协程","Repositories","Relational Databases"],"sub_categories":["协程/线程","Search and Analytic Databases","Coroutine/Thread","Advanced Console UIs","SQL 查询语句构建库","高級控制台界面","检索及分析资料库","\u003cspan id=\"高级控制台用户界面-advanced-console-uis\"\u003e高级控制台用户界面 Advanced Console UIs\u003c/span\u003e","高级控制台界面"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJeffail%2Ftunny","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJeffail%2Ftunny","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJeffail%2Ftunny/lists"}