{"action":"opened","issue":{"url":"https://api.github.com/repos/golang/go/issues/27837","repository_url":"https://api.github.com/repos/golang/go","labels_url":"https://api.github.com/repos/golang/go/issues/27837/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/27837/comments","events_url":"https://api.github.com/repos/golang/go/issues/27837/events","html_url":"https://github.com/golang/go/issues/27837","id":363364696,"node_id":"MDU6SXNzdWUzNjMzNjQ2OTY=","number":27837,"title":"x/sync/errgroup: add functionality to limit the number of simultaneous execution","user":{"login":"kurin","id":90267,"node_id":"MDQ6VXNlcjkwMjY3","avatar_url":"https://avatars1.githubusercontent.com/u/90267?v=4","gravatar_id":"","url":"https://api.github.com/users/kurin","html_url":"https://github.com/kurin","followers_url":"https://api.github.com/users/kurin/followers","following_url":"https://api.github.com/users/kurin/following{/other_user}","gists_url":"https://api.github.com/users/kurin/gists{/gist_id}","starred_url":"https://api.github.com/users/kurin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kurin/subscriptions","organizations_url":"https://api.github.com/users/kurin/orgs","repos_url":"https://api.github.com/users/kurin/repos","events_url":"https://api.github.com/users/kurin/events{/privacy}","received_events_url":"https://api.github.com/users/kurin/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-09-25T00:11:21Z","updated_at":"2018-09-25T00:11:21Z","closed_at":null,"author_association":"NONE","body":"The errgroup package will currently spawn a new goroutine for each invocation of Group.Go.  This is usually fine, but extremely high cardinality fanout can exhaust memory or other resources.  It would be neat if the errgroup interface allowed users to specify the maximum number of concurrent goroutines they want the errgroup to spawn.\r\n\r\n## Proposal\r\n\r\n```go\r\ntype Group struct {\r\n  N int\r\n  // contains etc\r\n}\r\n```\r\n\r\nN would be copied to an unexported on the first invocation of Go, so that subsequent modification has no effect.  This preserves the validity and the behavior of the empty Group.\r\n\r\nWhen calling Go, if the number of functions running is > N then Go would block until the number was <= N.\r\n\r\nThe behavior of Go is not otherwise modified; if a subtask returns an error, then subsequent tasks will still be executed, and callers would rely on subtasks handling context cancellation to fall through to the Wait() call and then return, if WithContext was called.\r\n\r\n## Alternatives considered\r\n\r\nAn alternative interface would be that Go never block, but enqueue instead.  This is an unbounded queue and I'm not a fan.\r\n\r\nAnother alternative is that the group is context-aware, and that Go return immediately if the group's context is cancelled.  This requires that Group retain a reference to the context, which it does not currently do."}}
{"actor":{"display_login":"kurin"}}