{"id":16643438,"url":"https://github.com/sonots/ruby-server-starter","last_synced_at":"2025-03-16T22:31:37.488Z","repository":{"id":28744998,"uuid":"32266827","full_name":"sonots/ruby-server-starter","owner":"sonots","description":"a superdaemon for hot-deploying server programs (ruby port of p5-Server-Starter)","archived":false,"fork":false,"pushed_at":"2022-05-09T08:38:34.000Z","size":52,"stargazers_count":50,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-13T08:08:40.912Z","etag":null,"topics":["puma","ruby","unicorn"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","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/sonots.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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-03-15T15:11:59.000Z","updated_at":"2024-03-29T02:09:10.000Z","dependencies_parsed_at":"2022-09-05T01:11:29.973Z","dependency_job_id":null,"html_url":"https://github.com/sonots/ruby-server-starter","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonots%2Fruby-server-starter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonots%2Fruby-server-starter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonots%2Fruby-server-starter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonots%2Fruby-server-starter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sonots","download_url":"https://codeload.github.com/sonots/ruby-server-starter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221668726,"owners_count":16860715,"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":["puma","ruby","unicorn"],"created_at":"2024-10-12T08:08:33.983Z","updated_at":"2024-10-27T11:28:54.988Z","avatar_url":"https://github.com/sonots.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ruby-server-starter\n\na superdaemon for hot-deploying server programs (ruby port of [p5-Server-Starter](https://github.com/kazuho/p5-Server-Starter))\n\n# Description\n\n*note: this description is almost entirely taken from the original Server::Starter module*\n\nThe ```start_server``` utility is a superdaemon for hot-deploying server programs.\n\nIt is often a pain to write a server program that supports graceful restarts, with no resource leaks. Server::Starter solves the problem by splitting the task into two: ```start_server``` works as a superdaemon that binds to zero or more TCP ports or unix sockets, and repeatedly spawns the server program that actually handles the necessary tasks (for example, responding to incoming commenctions). The spawned server programs under ```start_server``` call accept(2) and handle the requests.\n\nTo gracefully restart the server program, send SIGHUP to the superdaemon. The superdaemon spawns a new server program, and if (and only if) it starts up successfully, sends SIGTERM to the old server program.\n\nBy using ```start_server``` it is much easier to write a hot-deployable server. Following are the only requirements a server program to be run under ```start_server``` should conform to:\n\n- receive file descriptors to listen to through an environment variable\n- perform a graceful shutdown when receiving SIGTERM\n\n# Unicorn\n\nFollowing is an example to run unicorn server under ```Server::Starter```.\n\nThe command line example:\n\n```\nbundle exec start_server.rb \\\n  --port=10080 \\\n  --signal-on-hup=CONT \\\n  --dir=/path/to/app \\\n  --status-file=/path/to/app/log/start_server.stat \\\n  --pid-file=/path/to/app/log/start_server.pid \\\n  -- \\\n  bundle exec --keep-file-descriptors unicorn -c config/unicorn.conf.rb config.ru\n```\n\nAn example of unicorn.conf:\n\n```ruby\nrequire 'server/starter/unicorn_listener'\nlistener = Server::Starter::UnicornListener\n\nworker_processes  2\npreload_app true\n \nAPP_ROOT = File.expand_path('../..', __FILE__)\nstatus_file = File.join(APP_ROOT, 'log/start_server.stat')\n\nfd = listener.listen\nunless fd\n  # Fallback if not running under Server::Starter\n  listen ENV['PORT'] || '10080'\nend\n \nbefore_fork do |server, worker|\n  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!\n \n  # Throttle the master from forking too quickly by sleeping.  Due\n  # to the implementation of standard Unix signal handlers, this\n  # helps (but does not completely) prevent identical, repeated signals\n  # from being lost when the receiving process is busy.\n  sleep 1\nend\n \nafter_fork do |server, worker|\n  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection\n\n  # This is optional\n  #\n  # This allows a new master process to incrementally\n  # phase out the old master process with SIGTTOU to avoid a\n  # thundering herd (especially in the \"preload_app false\" case)\n  # when doing a transparent upgrade.  The last worker spawned\n  # will then kill off the old master process with a SIGQUIT.\n  listener.slow_start(server, worker, status_file)\nend\n```\n\n# Puma\n\nFollowing is an example to run puma server under ```Server::Starter```.\n\nThe command line example:\n\n```\nbundle exec start_server.rb \\\n  --port=0.0.0.0:10080 \\\n  --dir=/path/to/app \\\n  --interval=1 \\\n  --signal-on-hup=TERM \\\n  --signal-on-TERM=TERM \\\n  --pid-file=/path/to/app/log/start_server.pid \\\n  --status-file=/path/to/app/log/start_server.stat \\\n  --envdir=env \\\n  --enable-auto-restart \\\n  --auto-restart-interval=100 \\\n  --kill-old-delay=10 \\\n  --backlog=100 \\\n  -- \\\n  bundle exec --keep-file-descriptors start_puma.rb puma -C config/puma.rb config.ru\n```\n\nAn example of config/puma.rb:\n\n```ruby\n\nrequire 'server/starter/puma_listener'\nlistener = ::Server::Starter::PumaListener\n\nAPP_ROOT = File.expand_path('../..', __FILE__)\nstatus_file = File.join(APP_ROOT, 'log/start_server.stat')\n\npidfile File.join(APP_ROOT, 'log/puma.pid')\nstate_path File.join(APP_ROOT, 'log/puma.state')\n\n# prune_bundler # need to tweak lib/puma/launher to add { close_others: false } opts to Kernel.exec\npreload_app!\n\n# Configure \"min\" to be the minimum number of threads to use to answer\n# requests and \"max\" the maximum.\n# The default is \"0, 16\".\nthreads 0, 16\n\n# How many worker processes to run. The default is \"0\".\nworkers 2\n\n# Run puma via start_puma.rb to configure PUMA_INHERIT_\\d ENV from SERVER_STARTER_PORT ENV as\n# $ bundle exec --keep-file-descriptors start_puma.rb puma -C config/puma.conf.rb config.ru\nif ENV['SERVER_STARTER_PORT']\n  puma_inherits = listener.listen\n  puma_inherits.each do |puma_inherit|\n    bind puma_inherit[:url]\n  end\nelse\n  puts '[WARN] Fallback to 0.0.0.0:10080 since not running under Server::Starter'\n  bind 'tcp://0.0.0.0:10080'\nend\n\n# Code to run before doing a restart. This code should\n# close log files, database connections, etc.\n# This can be called multiple times to add code each time.\non_restart do\n  puts 'On restart...'\nend\n\n# Code to run when a worker boots to setup the process before booting\n# the app. This can be called multiple times to add hooks.\non_worker_boot do\n  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!\nend\n\n# Code to run when a worker boots to setup the process after booting\n# the app. This can be called multiple times to add hooks.\nafter_worker_boot do\n  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection\nend\n\n# Code to run when a worker shutdown.\non_worker_shutdown do\n  puts 'On worker shutdown...'\nend\n```\n\n## Options\n\nTo be written\n\n### --envdir [dir]\n\nConfigure environment variables from files on given directory, and reload on restarting.\n\nThe directory structure is inspired from [envdir](https://cr.yp.to/daemontools/envdir.html) of daemontools.\nThe filename is the environment variable name, and its content (first line) is the value of the environment variable.\n\nExample)\n\n```\n$ find env\nenv/RAILS_ENV\nenv/LANG\n```\n\n```\n$ cat env/RAILS_ENV\nproduction\n$ cat env/LANG\nen_US.UTF-8\n```\n\nwhich are equivalent with `env RAILS_ENV=production LANG=en_US.UTF-8` in shell.\n\nPlease note that environment variables are updated on restarting, which means deleted files are not affected.\n\n## See Also\n\n* [「Server::Starterに対応するとはどういうことか」の補足](http://blog.livedoor.jp/sonots/archives/40248661.html) (Japanese)\n* [Server::Starter で Unicorn を起動する場合の Slow Restart](http://blog.livedoor.jp/sonots/archives/42826057.html) (Japanese)\n* [Server::Starter を使って複数の Fluentd で１つのポートを待ち受ける](http://blog.livedoor.jp/sonots/archives/43219930.html) (Japanese)\n\n## ChangeLog\n\nSee [CHANGELOG.md](CHANGELOG.md) for details.\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new [Pull Request](../../pull/new/master)\n\n## Copyright\n\nCopyright (c) 2015 Naotoshi Seo. See [LICENSE](LICENSE) for details.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsonots%2Fruby-server-starter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsonots%2Fruby-server-starter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsonots%2Fruby-server-starter/lists"}