{"id":19565518,"url":"https://github.com/swaldman/mill-daemon","last_synced_at":"2025-07-25T13:10:21.384Z","repository":{"id":219533210,"uuid":"749271185","full_name":"swaldman/mill-daemon","owner":"swaldman","description":"A mill module that implements spawning of systemd-appropriate forking daemon processes","archived":false,"fork":false,"pushed_at":"2024-10-31T18:18:34.000Z","size":42,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-09T00:07:36.686Z","etag":null,"topics":["daemon","daemonize","mill","mill-module","mill-plugin","millbuild","systemd"],"latest_commit_sha":null,"homepage":"","language":"Scala","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/swaldman.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":"2024-01-28T04:11:10.000Z","updated_at":"2024-10-31T17:57:38.000Z","dependencies_parsed_at":"2024-11-11T05:28:00.212Z","dependency_job_id":"e90c705a-f06b-44e7-93be-24f13643a7af","html_url":"https://github.com/swaldman/mill-daemon","commit_stats":null,"previous_names":["swaldman/mill-daemon"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swaldman%2Fmill-daemon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swaldman%2Fmill-daemon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swaldman%2Fmill-daemon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swaldman%2Fmill-daemon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/swaldman","download_url":"https://codeload.github.com/swaldman/mill-daemon/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240824212,"owners_count":19863622,"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":["daemon","daemonize","mill","mill-module","mill-plugin","millbuild","systemd"],"created_at":"2024-11-11T05:27:22.768Z","updated_at":"2025-07-25T13:10:21.371Z","avatar_url":"https://github.com/swaldman.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mill-daemon\n\n### Introduction\n\nThis project enables [mill](https://mill-build.com/mill/Intro_to_Mill.html) to properly launch systemd\ndaemons that rebuild themselves with each restart.\n\nThis renders convenient configuration-as-compiler-checked code, or quick-editing of templates that convert to\ngenerated source code.\n\nWhen you use _mill_ as a launcher, you can simply edit your configuration-as-code or your templates, then hit\n`systemctl restart myservice` and watch your changes take immediate effect. You enjoy the ergonomics of an\ninterpreted language with the speed and typesafety of Scala.\n\n### How it works\n\n1. In `build.sc`, let your module extend [`DaemonModule`](src/com/mchange/milldaemon/DaemonModule.scala) defined in this library.\n   That will give you access to mill commands\n   * `runDaemon`\n   * `runMainDaemon`\n\n2. Override the function `def runDaemonPidFile : Option[os.Path]` to define a place where a PID file should be\n   written by _mill_ prior to shutting down, but after spawning your process.\n\n3. Include [mill wrapper](https://github.com/lefou/millw) in your project, and define a launch script that's something like\n   ```plaintext\n   #!/bin.bash\n\n   ./millw runMainDaemon mypkg.MyMain \"$@\"\n   ```\n   (This presumes you've also extended `RootModule`. Otherwise, specify `mymodulename.runMainDaemon`.)\n\n4. When you write your _systemd_ unit file, specify your daemon's `Type=forking`. Set `PIDFile=`\n   to the location you specified in `runDaemonPidFile`.\n\n5. Start your service (`systemctl start myservice`). Your service will build itself before it starts.\n   Edit stuff, templates, config, core source. Type `systemctl restart myservice` and it will all rebuild.\n\n### Advanced\n\n* If you asked mill to generate a PID file (by overriding `runDaemonPidFile`), your subprocess will have\n  `MILL_DAEMON_PID_FILE` in its environment. You can use this to, for example, set up a shutdown hook that\n  will delete the PID file when your process terminates.\n\n  * _If you are running daemons under_ systemd _, this is just a nice-to-have backstop!_ systemd\n    _will try to delete the PID file when your process terminates without your intervention.\n    If you do set a shudown hook to delete the PID file \n    **please check that the file is a file whose content is your process' PID before deleting**.\n    Don't blindly delete a file just because someone was able to get its path stuck in an environment variable._\n  * As of mill-daemon v0.1.2, there is now a supporting utility to help you do this properly!\n    Just include the dependency `com.mchange::mill-daemon-util:\u003cmill-daemon-version\u003e` in your build,\n    then\n\n    ```scala\n    import com.mchange.milldaemon.util.PidFileManager\n    \n    PidFileManager.installShutdownHookCarefulDelete()\n    ```\n\n* By default, the daemon subprocess inherits the `mill` launcher's standard-in and standard-out.\n  That gives _systemd_ control over where they should be directed, and is usually what you want.\n  However, you can override\n\n  * `def runDaemonOut : os.ProcessOutput`\n  * `def runDaemonErr : os.ProcessOutput`\n\n  to take control of these streams yourself, if you prefer.\n\n### Examples\n\n* Check out a [_feedletter installation_](https://github.com/swaldman/feedletter-tickle) for a simple example.\n\n### FAQ\n\n**Why not just use the `runBackground` and `runMainBackground` tasks built into `JavaModule`?**\n\nApplications started via `runBackground` and `runBackgroundMain` run embedded within a \n[`BackgroundWrapper`](https://github.com/com-lihaoyi/mill/blob/e171ad4c57c34a0bff2325327f8afc98d009f63d/scalalib/backgroundwrapper/src/mill/scalalib/backgroundwrapper/BackgroundWrapper.java) process which watches for changes in the files that built the application\nand quits when those occur. This is great, exactly what you want, when you are using the `mill -w` watch\nfeature. Whenever you change its source (loosely construed), your application quits and restarts so that\nyou enjoy prompt updates.\n\nHowever, this approach is not suitable for daemon processes, which are supposed to run stably and indefinitely,\nand should not terminate just because someone edits a file or runs a task in the directories from which they emerged.\n\nThe `runDaemon` tasks here give you clean daemons, mostly decoupled from any continued activity in the build directories\nafter the parent `mill` process terminates.\n\nWhen you update your `mill` build, use `systemctl restart \u003cservice\u003e`. Until a restart , the \"old\" service will\ncontinue in its old way.\n\n(In theory, the daemon may not be _completely_ decoupled from activity its launch directory. Infrequently accessed\nclasses compiled into the directory might not be loaded immediately upon daemon launch, and if they are\ndeleted or incompatibly upgraded, your daemon could break when it finally requires them. In practice, this would be unusual.\nNevertheless, daemon launch installations shouldn't be active development directories, just sites for occasional \nmodifications, reconfigurations, and relaunches.)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswaldman%2Fmill-daemon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswaldman%2Fmill-daemon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswaldman%2Fmill-daemon/lists"}