{"id":29117205,"url":"https://github.com/skovtunenko/graterm","last_synced_at":"2026-01-12T02:51:10.462Z","repository":{"id":41469411,"uuid":"509708743","full_name":"skovtunenko/graterm","owner":"skovtunenko","description":"Provides primitives to perform ordered GRAceful TERmination for Golang applications","archived":false,"fork":false,"pushed_at":"2025-02-23T19:47:24.000Z","size":105,"stargazers_count":27,"open_issues_count":3,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-23T20:22:06.208Z","etag":null,"topics":["graceful-degradation","graceful-restart-process","graceful-shutdown","graceful-stop","gracefull","gracefully","shutdown","shutdown-helper","shutdown-hook","shutdown-manager","shutdown-service","termination"],"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/skovtunenko.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":"2022-07-02T09:07:30.000Z","updated_at":"2025-02-23T19:47:26.000Z","dependencies_parsed_at":"2025-02-23T20:21:15.156Z","dependency_job_id":"aec72cdd-9ec9-4dc6-94cb-2a80693fec40","html_url":"https://github.com/skovtunenko/graterm","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/skovtunenko/graterm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skovtunenko%2Fgraterm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skovtunenko%2Fgraterm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skovtunenko%2Fgraterm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skovtunenko%2Fgraterm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skovtunenko","download_url":"https://codeload.github.com/skovtunenko/graterm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skovtunenko%2Fgraterm/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262581514,"owners_count":23331925,"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":["graceful-degradation","graceful-restart-process","graceful-shutdown","graceful-stop","gracefull","gracefully","shutdown","shutdown-helper","shutdown-hook","shutdown-manager","shutdown-service","termination"],"created_at":"2025-06-29T11:14:15.060Z","updated_at":"2026-01-12T02:51:10.435Z","avatar_url":"https://github.com/skovtunenko.png","language":"Go","funding_links":[],"categories":["公用事业公司","Utilities"],"sub_categories":["实用程序/Miscellaneous","Utility/Miscellaneous"],"readme":"# graterm\n\n[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)\n![Lint](https://github.com/skovtunenko/graterm/actions/workflows/golangci-lint.yml/badge.svg?branch=main)\n![Tests](https://github.com/skovtunenko/graterm/actions/workflows/test.yml/badge.svg?branch=main)\n[![codecov](https://codecov.io/gh/skovtunenko/graterm/branch/main/graph/badge.svg)](https://codecov.io/gh/skovtunenko/graterm)\n[![Go Report Card](https://goreportcard.com/badge/github.com/skovtunenko/graterm)](https://goreportcard.com/report/github.com/skovtunenko/graterm)\n[![License](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/skovtunenko/graterm/blob/main/LICENSE)\n[![GoDoc](https://godoc.org/github.com/skovtunenko/graterm?status.svg)](https://godoc.org/github.com/skovtunenko/graterm)\n[![Release](https://img.shields.io/github/release/skovtunenko/graterm.svg?style=flat-square)](https://github.com/skovtunenko/graterm/releases/latest)\n\nProvides primitives to perform ordered **GRA**ceful **TERM**ination (aka shutdown) in Go application.\n\n# ⚡ ️️Description\n\nLibrary provides fluent methods to register ordered application termination (aka shutdown) [hooks](https://pkg.go.dev/github.com/skovtunenko/graterm#Hook),\nand block the main goroutine until the registered `os.Signal` will occur. \n\nTermination [hooks](https://pkg.go.dev/github.com/skovtunenko/graterm#Hook) registered with the \nsame [Order](https://pkg.go.dev/github.com/skovtunenko/graterm#Order) will be executed concurrently.\n\nIt is possible to set individual timeouts for each registered termination [hook](https://pkg.go.dev/github.com/skovtunenko/graterm#Hook) \nand global termination timeout for the whole application.\n\n# 🎯 Features\n\n* Dependency only on a standard Go library (except tests).\n* Component-agnostic (can be adapted to any 3rd party technology).\n* Clean and tested code: 100% test coverage, including goroutine leak tests.\n* Rich set of examples.\n\n# ⚙️ Usage\n\nGet the library:\n\n```bash\ngo get -u github.com/skovtunenko/graterm\n```\n\nImport the library into the project:\n\n```go\nimport (\n    \"github.com/skovtunenko/graterm\"\n)\n```\n\nCreate a new instance of [Terminator](https://pkg.go.dev/github.com/skovtunenko/graterm#Terminator) and get an application context \nthat will be cancelled when one of the registered `os.Signal`s will occur:\n\n```go\n// create new Terminator instance:\nterminator, appCtx := graterm.NewWithSignals(context.Background(), syscall.SIGINT, syscall.SIGTERM)\n// Optionally set the custom logger implementation instead of default NOOP one:\nterminator.SetLogger(log.Default()) \n```\n\nOptionally define [Order](https://pkg.go.dev/github.com/skovtunenko/graterm#Order) of components to be terminated at the end:\n\n```go\nconst (\n    HTTPServerTerminationOrder graterm.Order = 1\n    MessagingTerminationOrder  graterm.Order = 1\n    DBTerminationOrder         graterm.Order = 2\n    // ..........\n)\n```\n\nRegister some termination [Hooks](https://pkg.go.dev/github.com/skovtunenko/graterm#Hook) with priorities:\n\n```go\nterminator.WithOrder(HTTPServerTerminationOrder).\n    WithName(\"HTTP Server\"). // setting a Name is optional and will be useful only if logger instance provided\n    Register(1*time.Second, func(ctx context.Context) {\n        if err := httpServer.Shutdown(ctx); err != nil {\n            log.Printf(\"shutdown HTTP Server: %+v\\n\", err)\n        }\n    })\n```\n\nBlock main goroutine until the application receives one of the registered `os.Signal`s:\n\n```go\nif err := terminator.Wait(appCtx, 20 * time.Second); err != nil {\n    log.Printf(\"graceful termination period was timed out: %+v\", err)\n}\n```\n\n# 👀 Versioning\n\nThe library follows SemVer policy. With the release of **v1.0.0** the _public API is stable_. \n\n# 📚 Example\n\nEach public function has example attached to it. Here is the simple one:\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n    \"syscall\"\n    \"time\"\n\n    \"github.com/skovtunenko/graterm\"\n)\n\nfunc main() {\n    // Define Orders:\n    const (\n        HTTPServerTerminationOrder graterm.Order = 1\n        MessagingTerminationOrder  graterm.Order = 1\n        DBTerminationOrder         graterm.Order = 2\n    )\n\n    // create new Terminator instance:\n    terminator, appCtx := graterm.NewWithSignals(context.Background(), syscall.SIGINT, syscall.SIGTERM)\n    terminator.SetLogger(log.Default()) // Optional step\n\n    // Register HTTP Server termination hook:\n    terminator.WithOrder(HTTPServerTerminationOrder).\n        WithName(\"HTTP Server\"). // setting a Name is optional and will be useful only if logger instance provided\n        Register(1*time.Second, func(ctx context.Context) {\n            log.Println(\"terminating HTTP Server...\")\n            defer log.Println(\"...HTTP Server terminated\")\n        })\n\n    // Register nameless Messaging termination hook:\n    terminator.WithOrder(MessagingTerminationOrder).\n        Register(1*time.Second, func(ctx context.Context) {\n            log.Println(\"terminating Messaging...\")\n            defer log.Println(\"...Messaging terminated\")\n        })\n\n    // Register Database termination hook:\n    terminator.WithOrder(DBTerminationOrder).\n        WithName(\"DB\"). // setting a Name is optional and will be useful only if logger instance provided\n        Register(1*time.Second, func(ctx context.Context) {\n            log.Println(\"terminating DB...\")\n            defer log.Println(\"...DB terminated\")\n\n            const sleepTime = 3 * time.Second\n            select {\n            case \u003c-time.After(sleepTime):\n                log.Printf(\"DB termination sleep time %v is over\\n\", sleepTime)\n            case \u003c-ctx.Done():\n                log.Printf(\"DB termination Context is Done because of: %+v\\n\", ctx.Err())\n            }\n        })\n\n    // Wait for os.Signal to occur, then terminate application with maximum timeout of 20 seconds:\n    if err := terminator.Wait(appCtx, 20 * time.Second); err != nil {\n        log.Printf(\"graceful termination period was timed out: %+v\", err)\n    }\n}\n```\n\n💡 Integration with HTTP server\n-----------\n\nThe library doesn't have out of the box support to start/terminate the HTTP server, but that's easy to handle:\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"errors\"\n    \"fmt\"\n    \"log\"\n    \"net/http\"\n    \"syscall\"\n    \"time\"\n\n    \"github.com/skovtunenko/graterm\"\n)\n\nfunc main() {\n    // Define Order for HTTP Server termination:\n    const HTTPServerTerminationOrder graterm.Order = 1\n\n    // create new Terminator instance:\n    terminator, appCtx := graterm.NewWithSignals(context.Background(), syscall.SIGINT, syscall.SIGTERM)\n    terminator.SetLogger(log.Default()) // Optional step\n\n    // Create an HTTP Server and add one simple handler into it:\n    httpServer := \u0026http.Server{\n        Addr:              \":8080\",\n        Handler:           http.DefaultServeMux,\n    }\n    http.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n        fmt.Fprintf(w, \"hello, world!\")\n    })\n\n    // Start HTTP server in a separate goroutine:\n    go func() { \n        if err := httpServer.ListenAndServe(); err != nil \u0026\u0026 !errors.Is(err, http.ErrServerClosed) {\n            log.Printf(\"terminated HTTP Server: %+v\\n\", err)\n        }\n    }()\n\n    // Register HTTP Server termination hook:\n    terminator.WithOrder(HTTPServerTerminationOrder).\n        WithName(\"HTTPServer\"). // setting a Name is optional and will be useful only if logger instance provided\n        Register(10*time.Second, func(ctx context.Context) {\n            if err := httpServer.Shutdown(ctx); err != nil {\n                log.Printf(\"shutdown HTTP Server: %+v\\n\", err)\n            }\n        })\n\n    // Wait for os.Signal to occur, then terminate application with maximum timeout of 30 seconds:\n    if err := terminator.Wait(appCtx, 30*time.Second); err != nil {\n        log.Printf(\"graceful termination period is timed out: %+v\\n\", err)\n    }\n}\n```\n\nThe full-fledged example located here: [example.go](https://github.com/skovtunenko/graterm/blob/main/internal/example/example.go)\n\n📖 Testing\n-----------\n\nUnit-tests with code coverage:\n\n```bash\nmake test\n```\n\nRun linter:\n\n```bash\nmake code-quality\n```\n\n⚠️ LICENSE\n-----------\n\n[MIT](https://github.com/skovtunenko/graterm/blob/main/LICENSE)\n\n🕶️ AUTHORS\n-----------\n\n* [Sergiy Kovtunenko](https://github.com/skovtunenko)\n* [Oleksandr Halushchak](ohalushchak@exadel.com)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskovtunenko%2Fgraterm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskovtunenko%2Fgraterm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskovtunenko%2Fgraterm/lists"}