{"id":33098492,"url":"https://github.com/teris-io/longpoll","last_synced_at":"2026-01-20T12:02:17.348Z","repository":{"id":57577444,"uuid":"48646743","full_name":"teris-io/longpoll","owner":"teris-io","description":"Parked: PubSub queuing with long-polling subscribers (not bound to http)","archived":false,"fork":false,"pushed_at":"2017-12-17T08:47:00.000Z","size":74,"stargazers_count":35,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-14T12:32:00.708Z","etag":null,"topics":["long-polling","pubsub"],"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/teris-io.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-12-27T13:49:55.000Z","updated_at":"2024-08-19T12:38:28.000Z","dependencies_parsed_at":"2022-09-11T22:50:59.752Z","dependency_job_id":null,"html_url":"https://github.com/teris-io/longpoll","commit_stats":null,"previous_names":["ventu-io/go-longpoll"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/teris-io/longpoll","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teris-io%2Flongpoll","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teris-io%2Flongpoll/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teris-io%2Flongpoll/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teris-io%2Flongpoll/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/teris-io","download_url":"https://codeload.github.com/teris-io/longpoll/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teris-io%2Flongpoll/sbom","scorecard":{"id":874367,"data":{"date":"2025-08-11","repo":{"name":"github.com/teris-io/longpoll","commit":"dc275acaf1510c8ad89ffae5ba9ee10f77720440"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/26 approved changesets -- score normalized to 0","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":"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":"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":"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":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"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 6 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-24T05:24:43.751Z","repository_id":57577444,"created_at":"2025-08-24T05:24:43.751Z","updated_at":"2025-08-24T05:24:43.751Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28506593,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T10:25:30.148Z","status":"ssl_error","status_checked_at":"2026-01-17T10:25:29.718Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["long-polling","pubsub"],"created_at":"2025-11-14T21:00:21.452Z","updated_at":"2026-01-20T12:02:17.339Z","avatar_url":"https://github.com/teris-io.png","language":"Go","funding_links":[],"categories":["Messaging"],"sub_categories":["Advanced Console UIs"],"readme":"[![Build status][buildimage]][build] [![Coverage][codecovimage]][codecov] [![GoReportCard][cardimage]][card] [![API documentation][docsimage]][docs]\n\n# Parked: PubSub with long polling in Go\n\nThe package `longpoll` provides an implementation of the\nlong-polling mechanism of the PubSub pattern. Although the primary purpose of the\nlibrary is to aid the development of web applications, the library provides no specific web\nhandlers and  can be used in other distributed applications.\n\nLong polling is a technique to notify client applications about updates on the server. It is often\nused in writing web application as a substitute for the push technique, however can be used in\nother distributed applications.\n\nClients initiate subscriptions to the server specifying topics they are interested in. Given a\nsubscription Id a client makes a request for new data. The request is held open until data becomes\navailable on the server (published to a matching topic). As soon as this happens the request is\nanswered immediately. If no data arrives over a predefined time window (the long-polling interval)\nthe request returns empty. A new connection is then established between the client and the server\nto receive further updates.\n\nThe following points are often listed as the benefits of long-polling over the push mechanism in web\napplications:\n\n* does not require a persistent connection to the server\n* works for slow clients as they receive information at the speed they can process, although\nmaybe in large chunks which are accumulated at the server between requests\n* friendly to proxies blocking streaming\n\n\n## Implementation details and examples\n\nSubscriptions will timeout and get closed if no client request is received over a given timeout\ninterval. Every request resets the timeout counter. The timeout interval is a property of the\nsubscription itself and different subscriptions may have different timeout intervals.\n\nThe long-polling interval, within which the request is held, is specified per request. Web\napplication wrappers might provide defaults.\n\nThe library supports concurrent long-polling requests on the same subscription Id, but no data will\nbe duplicated across request responses. No specific distribution of data across responses is\nguaranteed: new requests signal the existing one to return immediately.\n\nAt the moment the library does not support persisting of published data before it is collected by\nsubscribers. All the published data is stored in memory of the backend.\n\n\n**Long-polling with subscription management:**\n\nHandling of long-polling subscriptions, publishing and receiving data is done by the\n`longpoll.LongPoll` type:\n\n```go\nps := longpoll.New()\nid1, _ := ps.Subscribe(time.Minute, \"TopicA\", \"TopicB\")\nid2, _ := ps.Subscribe(time.Minute, \"TopicB\", \"TopicC\")\n\ngo func() {\n  for {\n    if datach, err := ps.Get(id1, 30*time.Second); err == nil {\n      fmt.Printf(\"%v received %v\", id1, \u003c-datach)\n    } else {\n      break\n    }\n  }\n}()\n\ngo func() {\n  for {\n    if datach, err := ps.Get(id2, 20*time.Second); err == nil {\n      fmt.Printf(\"%v received %v\", id2, \u003c-datach)\n    } else {\n      break\n    }\n  }\n}()\n\nfor {\n  // data published on TopicB will be received by id1 and id2, TopicC by id2 only\n  ps.Publish({\"random\": rand.Float64()}, \"TopicB\", \"TopicC\")\n\n  // sleep for up to 50s\n  time.Sleep(time.Duration(rand.Intn(5e10)))\n}\n```\n\n**Long-polling on a single subscription channel:**\n\nHandling of the single-channel long-polling pubsub is done by the `longpoll.Sub` type:\n\n```go\nch := longpoll.MustNewChannel(time.Minute, func (id string) {\n  // action on exit\n}, \"TopicA\", \"TopicB\")\n\ngo func() {\n  for {\n    if datach, err := ch.Get(20*time.Second); err == nil {\n      fmt.Printf(\"received %v\", \u003c-datach)\n    } else {\n      break\n    }\n  }\n}()\n\nfor {\n  ch.Publish({\"random\": rand.Float64()}, \"TopicB\")\n  // above subscription will not receive this data\n  ch.Publish({\"random\": rand.Float64()}, \"TopicC\")\n\n  // sleep for up to 50s\n  time.Sleep(time.Duration(rand.Intn(5e10)))\n}\n```\n\n### License and copyright\n\n\tCopyright (c) 2015-2017. Oleg Sklyar and teris.io. MIT license applies. All rights reserved.\n\n\n[build]: https://travis-ci.org/teris-io/longpoll\n[buildimage]: https://travis-ci.org/teris-io/longpoll.svg?branch=master\n\n[codecov]: https://codecov.io/github/teris-io/longpoll?branch=master\n[codecovimage]: https://codecov.io/github/teris-io/longpoll/coverage.svg?branch=master\n\n[card]: http://goreportcard.com/report/teris-io/longpoll\n[cardimage]: https://goreportcard.com/badge/github.com/teris-io/longpoll\n\n[docs]: https://godoc.org/github.com/teris-io/longpoll\n[docsimage]: http://img.shields.io/badge/godoc-reference-blue.svg?style=flat\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteris-io%2Flongpoll","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fteris-io%2Flongpoll","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteris-io%2Flongpoll/lists"}