{"id":36784939,"url":"https://github.com/desertbit/timer","last_synced_at":"2026-01-12T13:20:10.763Z","repository":{"id":57487226,"uuid":"76176455","full_name":"desertbit/timer","owner":"desertbit","description":" Go Timer implementation with a fixed Reset behavior","archived":false,"fork":false,"pushed_at":"2024-06-14T13:52:48.000Z","size":15,"stargazers_count":32,"open_issues_count":0,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-06-18T15:31:15.665Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/desertbit.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":"2016-12-11T13:36:55.000Z","updated_at":"2024-06-14T13:52:44.000Z","dependencies_parsed_at":"2024-06-18T15:25:53.004Z","dependency_job_id":null,"html_url":"https://github.com/desertbit/timer","commit_stats":{"total_commits":14,"total_committers":1,"mean_commits":14.0,"dds":0.0,"last_synced_commit":"c41aec40b27f0eeb2b94300fffcd624c69b02990"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/desertbit/timer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/desertbit%2Ftimer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/desertbit%2Ftimer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/desertbit%2Ftimer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/desertbit%2Ftimer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/desertbit","download_url":"https://codeload.github.com/desertbit/timer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/desertbit%2Ftimer/sbom","scorecard":{"id":336032,"data":{"date":"2025-08-11","repo":{"name":"github.com/desertbit/timer","commit":"eef2e214094da53514b165f796a372833168efbe"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"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":"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":"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":"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":"Code-Review","score":0,"reason":"Found 1/17 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":"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":"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":"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":"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 2 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"}},{"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"}}]},"last_synced_at":"2025-08-18T04:45:03.167Z","repository_id":57487226,"created_at":"2025-08-18T04:45:03.167Z","updated_at":"2025-08-18T04:45:03.167Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28338996,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T12:22:26.515Z","status":"ssl_error","status_checked_at":"2026-01-12T12:22:10.856Z","response_time":98,"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":[],"created_at":"2026-01-12T13:20:05.707Z","updated_at":"2026-01-12T13:20:10.646Z","avatar_url":"https://github.com/desertbit.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Go Timer implementation with a fixed Reset behavior\n\n[![GoDoc](https://godoc.org/github.com/desertbit/timer?status.svg)](https://godoc.org/github.com/desertbit/timer)\n[![Go Report Card](https://goreportcard.com/badge/github.com/desertbit/timer)](https://goreportcard.com/report/github.com/desertbit/timer)\n\nThis is a lightweight timer implementation which is a drop-in replacement for\nGo's Timer. Reset behaves as one would expect and drains the timer.C channel automatically.\nThe core design of this package is similar to the original runtime timer implementation.\n\nThese two lines are equivalent except for saving some garbage:\n\n```go\nt.Reset(x)\n\nt := timer.NewTimer(x)\n```\n\nSee issues:\n- https://github.com/golang/go/issues/11513\n- https://github.com/golang/go/issues/14383\n- https://github.com/golang/go/issues/12721\n- https://github.com/golang/go/issues/14038\n- https://groups.google.com/forum/#!msg/golang-dev/c9UUfASVPoU/tlbK2BpFEwAJ\n- http://grokbase.com/t/gg/golang-nuts/1571eh3tv7/go-nuts-reusing-time-timer\n\nQuote from the [Timer Go doc reference](https://golang.org/pkg/time/#Timer):\n\n\u003eReset changes the timer to expire after duration d.\nIt returns true if the timer had been active, false if the timer had\nexpired or been stopped.\n\n\u003e To reuse an active timer, always call its Stop method first and—if it had\nexpired—drain the value from its channel. For example: [...]\nThis should not be done concurrent to other receives from the Timer's channel.\n\n\u003e Note that it is not possible to use Reset's return value correctly, as there\nis a race condition between draining the channel and the new timer expiring.\nReset should always be used in concert with Stop, as described above.\nThe return value exists to preserve compatibility with existing programs.\n\n## Broken behavior sample\n\n### Sample 1\n\n```go\npackage main\n\nimport (\n    \"log\"\n    \"time\"\n)\n\nfunc main() {\n\tstart := time.Now()\n\n\t// Start a new timer with a timeout of 1 second.\n\ttimer := time.NewTimer(1 * time.Second)\n\n\t// Wait for 2 seconds.\n\t// Meanwhile the timer fired and filled the channel.\n\ttime.Sleep(2 * time.Second)\n\n\t// Reset the timer. This should act exactly as creating a new timer.\n\ttimer.Reset(1 * time.Second)\n\n\t// However this will fire immediately, because the channel was not drained.\n\t// See issue: https://github.com/golang/go/issues/11513\n\t\u003c-timer.C\n\n\tif int(time.Since(start).Seconds()) != 3 {\n\t\tlog.Fatalf(\"took ~%v seconds, should be ~3 seconds\\n\", int(time.Since(start).Seconds()))\n\t}\n}\n```\n\n### Sample 2\n\n```go\npackage main\n\nimport \"time\"\n\nconst (\n\tkeepaliveInterval = 2 * time.Millisecond\n)\n\nvar (\n\tresetC = make(chan struct{}, 1)\n)\n\nfunc main() {\n\tgo keepaliveLoop()\n\n\t// Sample routine triggering the reset.\n\t// Example: this could be due to incoming peer requests and\n\t// a keepalive check should be reset to the max keepalive timeout.\n\tfor i := 0; i \u003c 1000; i++ {\n\t\ttime.Sleep(time.Millisecond)\n\t\tresetKeepalive()\n\t}\n}\n\nfunc resetKeepalive() {\n\t// Don't block if there is already a reset request.\n\tselect {\n\tcase resetC \u003c- struct{}{}:\n\tdefault:\n\t}\n}\n\nfunc keepaliveLoop() {\n\tt := time.NewTimer(keepaliveInterval)\n\n\tfor {\n\t\tselect {\n\t\tcase \u003c-resetC:\n\t\t\ttime.Sleep(3 * time.Millisecond) // Simulate some reset work...\n\t\t\tt.Reset(keepaliveInterval)\n\t\tcase \u003c-t.C:\n\t\t\tping()\n\t\t\tt.Reset(keepaliveInterval)\n\t\t}\n\t}\n}\n\nfunc ping() {\n\tpanic(\"ping must not be called in this example\")\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdesertbit%2Ftimer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdesertbit%2Ftimer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdesertbit%2Ftimer/lists"}