daemon.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package cli // import "miniflux.app/v2/internal/cli"
  4. import (
  5. "context"
  6. "log/slog"
  7. "net/http"
  8. "os"
  9. "os/signal"
  10. "syscall"
  11. "time"
  12. "miniflux.app/v2/internal/config"
  13. "miniflux.app/v2/internal/http/server"
  14. "miniflux.app/v2/internal/metric"
  15. "miniflux.app/v2/internal/storage"
  16. "miniflux.app/v2/internal/systemd"
  17. "miniflux.app/v2/internal/worker"
  18. )
  19. func startDaemon(store *storage.Storage) {
  20. slog.Debug("Starting daemon...")
  21. stop := make(chan os.Signal, 1)
  22. signal.Notify(stop, os.Interrupt)
  23. signal.Notify(stop, syscall.SIGTERM)
  24. pool := worker.NewPool(store, config.Opts.WorkerPoolSize())
  25. if config.Opts.HasSchedulerService() && !config.Opts.HasMaintenanceMode() {
  26. runScheduler(store, pool)
  27. }
  28. var httpServers []*http.Server
  29. if config.Opts.HasHTTPService() {
  30. httpServers = server.StartWebServer(store, pool)
  31. }
  32. if config.Opts.HasMetricsCollector() {
  33. collector := metric.NewCollector(store, config.Opts.MetricsRefreshInterval())
  34. go collector.GatherStorageMetrics()
  35. }
  36. if systemd.HasNotifySocket() {
  37. slog.Debug("Sending readiness notification to Systemd")
  38. if err := systemd.SdNotify(systemd.SdNotifyReady); err != nil {
  39. slog.Error("Unable to send readiness notification to systemd", slog.Any("error", err))
  40. }
  41. if config.Opts.HasWatchdog() && systemd.HasSystemdWatchdog() {
  42. slog.Debug("Activating Systemd watchdog")
  43. go func() {
  44. interval, err := systemd.WatchdogInterval()
  45. if err != nil {
  46. slog.Error("Unable to get watchdog interval from systemd", slog.Any("error", err))
  47. return
  48. }
  49. for {
  50. if err := store.Ping(); err != nil {
  51. slog.Error("Unable to ping database", slog.Any("error", err))
  52. } else {
  53. systemd.SdNotify(systemd.SdNotifyWatchdog)
  54. }
  55. time.Sleep(interval / 3)
  56. }
  57. }()
  58. }
  59. }
  60. <-stop
  61. slog.Debug("Shutting down the process")
  62. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  63. defer cancel()
  64. if len(httpServers) > 0 {
  65. slog.Debug("Shutting down HTTP servers...")
  66. for _, server := range httpServers {
  67. if server != nil {
  68. if err := server.Shutdown(ctx); err != nil {
  69. slog.Error("HTTP server shutdown error", slog.Any("error", err), slog.String("addr", server.Addr))
  70. }
  71. }
  72. }
  73. slog.Debug("All HTTP servers shut down.")
  74. } else {
  75. slog.Debug("No HTTP servers to shut down.")
  76. }
  77. slog.Debug("Process gracefully stopped")
  78. }