server_manager.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package server
  2. import (
  3. "heckel.io/ntfy/log"
  4. "heckel.io/ntfy/util"
  5. "strings"
  6. )
  7. func (s *Server) execManager() {
  8. // WARNING: Make sure to only selectively lock with the mutex, and be aware that this
  9. // there is no mutex for the entire function.
  10. // Prune all the things
  11. s.pruneVisitors()
  12. s.pruneTokens()
  13. s.pruneAttachments()
  14. s.pruneMessages()
  15. // Message count per topic
  16. var messagesCached int
  17. messageCounts, err := s.messageCache.MessageCounts()
  18. if err != nil {
  19. log.Tag(tagManager).Err(err).Warn("Cannot get message counts")
  20. messageCounts = make(map[string]int) // Empty, so we can continue
  21. }
  22. for _, count := range messageCounts {
  23. messagesCached += count
  24. }
  25. // Remove subscriptions without subscribers
  26. var emptyTopics, subscribers int
  27. log.
  28. Tag(tagManager).
  29. Timing(func() {
  30. s.mu.Lock()
  31. defer s.mu.Unlock()
  32. for _, t := range s.topics {
  33. subs, lastAccess := t.Stats()
  34. ev := log.Tag(tagManager).With(t)
  35. if t.Stale() {
  36. if ev.IsTrace() {
  37. ev.Trace("- topic %s: Deleting stale topic (%d subscribers, accessed %s)", t.ID, subs, util.FormatTime(lastAccess))
  38. }
  39. emptyTopics++
  40. delete(s.topics, t.ID)
  41. } else {
  42. if ev.IsTrace() {
  43. ev.Trace("- topic %s: %d subscribers, accessed %s", t.ID, subs, util.FormatTime(lastAccess))
  44. }
  45. subscribers += subs
  46. }
  47. }
  48. }).
  49. Debug("Removed %d empty topic(s)", emptyTopics)
  50. // Mail stats
  51. var receivedMailTotal, receivedMailSuccess, receivedMailFailure int64
  52. if s.smtpServerBackend != nil {
  53. receivedMailTotal, receivedMailSuccess, receivedMailFailure = s.smtpServerBackend.Counts()
  54. }
  55. var sentMailTotal, sentMailSuccess, sentMailFailure int64
  56. if s.smtpSender != nil {
  57. sentMailTotal, sentMailSuccess, sentMailFailure = s.smtpSender.Counts()
  58. }
  59. // Print stats
  60. s.mu.Lock()
  61. messagesCount, topicsCount, visitorsCount := s.messages, len(s.topics), len(s.visitors)
  62. s.mu.Unlock()
  63. log.
  64. Tag(tagManager).
  65. Fields(log.Context{
  66. "messages_published": messagesCount,
  67. "messages_cached": messagesCached,
  68. "topics_active": topicsCount,
  69. "subscribers": subscribers,
  70. "visitors": visitorsCount,
  71. "emails_received": receivedMailTotal,
  72. "emails_received_success": receivedMailSuccess,
  73. "emails_received_failure": receivedMailFailure,
  74. "emails_sent": sentMailTotal,
  75. "emails_sent_success": sentMailSuccess,
  76. "emails_sent_failure": sentMailFailure,
  77. }).
  78. Info("Server stats")
  79. if s.httpMetricsServer != nil {
  80. metrics.messagesCached.Set(float64(messagesCached))
  81. metrics.visitors.Set(float64(visitorsCount))
  82. metrics.subscribers.Set(float64(subscribers))
  83. metrics.topics.Set(float64(topicsCount))
  84. }
  85. }
  86. func (s *Server) pruneVisitors() {
  87. staleVisitors := 0
  88. log.
  89. Tag(tagManager).
  90. Timing(func() {
  91. s.mu.Lock()
  92. defer s.mu.Unlock()
  93. for ip, v := range s.visitors {
  94. if v.Stale() {
  95. log.Tag(tagManager).With(v).Trace("Deleting stale visitor")
  96. delete(s.visitors, ip)
  97. staleVisitors++
  98. }
  99. }
  100. }).
  101. Field("stale_visitors", staleVisitors).
  102. Debug("Deleted %d stale visitor(s)", staleVisitors)
  103. }
  104. func (s *Server) pruneTokens() {
  105. if s.userManager != nil {
  106. log.
  107. Tag(tagManager).
  108. Timing(func() {
  109. if err := s.userManager.RemoveExpiredTokens(); err != nil {
  110. log.Tag(tagManager).Err(err).Warn("Error expiring user tokens")
  111. }
  112. if err := s.userManager.RemoveDeletedUsers(); err != nil {
  113. log.Tag(tagManager).Err(err).Warn("Error deleting soft-deleted users")
  114. }
  115. }).
  116. Debug("Removed expired tokens and users")
  117. }
  118. }
  119. func (s *Server) pruneAttachments() {
  120. if s.fileCache == nil {
  121. return
  122. }
  123. log.
  124. Tag(tagManager).
  125. Timing(func() {
  126. ids, err := s.messageCache.AttachmentsExpired()
  127. if err != nil {
  128. log.Tag(tagManager).Err(err).Warn("Error retrieving expired attachments")
  129. } else if len(ids) > 0 {
  130. if log.Tag(tagManager).IsDebug() {
  131. log.Tag(tagManager).Debug("Deleting attachments %s", strings.Join(ids, ", "))
  132. }
  133. if err := s.fileCache.Remove(ids...); err != nil {
  134. log.Tag(tagManager).Err(err).Warn("Error deleting attachments")
  135. }
  136. if err := s.messageCache.MarkAttachmentsDeleted(ids...); err != nil {
  137. log.Tag(tagManager).Err(err).Warn("Error marking attachments deleted")
  138. }
  139. } else {
  140. log.Tag(tagManager).Debug("No expired attachments to delete")
  141. }
  142. }).
  143. Debug("Deleted expired attachments")
  144. }
  145. func (s *Server) pruneMessages() {
  146. log.
  147. Tag(tagManager).
  148. Timing(func() {
  149. expiredMessageIDs, err := s.messageCache.MessagesExpired()
  150. if err != nil {
  151. log.Tag(tagManager).Err(err).Warn("Error retrieving expired messages")
  152. } else if len(expiredMessageIDs) > 0 {
  153. if s.fileCache != nil {
  154. if err := s.fileCache.Remove(expiredMessageIDs...); err != nil {
  155. log.Tag(tagManager).Err(err).Warn("Error deleting attachments for expired messages")
  156. }
  157. }
  158. if err := s.messageCache.DeleteMessages(expiredMessageIDs...); err != nil {
  159. log.Tag(tagManager).Err(err).Warn("Error marking attachments deleted")
  160. }
  161. } else {
  162. log.Tag(tagManager).Debug("No expired messages to delete")
  163. }
  164. }).
  165. Debug("Pruned messages")
  166. }