code.gitea.io/gitea@v1.19.3/modules/eventsource/manager_run.go (about) 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package eventsource 5 6 import ( 7 "context" 8 "time" 9 10 activities_model "code.gitea.io/gitea/models/activities" 11 issues_model "code.gitea.io/gitea/models/issues" 12 "code.gitea.io/gitea/modules/graceful" 13 "code.gitea.io/gitea/modules/json" 14 "code.gitea.io/gitea/modules/log" 15 "code.gitea.io/gitea/modules/process" 16 "code.gitea.io/gitea/modules/setting" 17 "code.gitea.io/gitea/modules/timeutil" 18 "code.gitea.io/gitea/services/convert" 19 ) 20 21 // Init starts this eventsource 22 func (m *Manager) Init() { 23 if setting.UI.Notification.EventSourceUpdateTime <= 0 { 24 return 25 } 26 go graceful.GetManager().RunWithShutdownContext(m.Run) 27 } 28 29 // Run runs the manager within a provided context 30 func (m *Manager) Run(ctx context.Context) { 31 ctx, _, finished := process.GetManager().AddTypedContext(ctx, "Service: EventSource", process.SystemProcessType, true) 32 defer finished() 33 34 then := timeutil.TimeStampNow().Add(-2) 35 timer := time.NewTicker(setting.UI.Notification.EventSourceUpdateTime) 36 loop: 37 for { 38 select { 39 case <-ctx.Done(): 40 timer.Stop() 41 break loop 42 case <-timer.C: 43 m.mutex.Lock() 44 connectionCount := len(m.messengers) 45 if connectionCount == 0 { 46 log.Trace("Event source has no listeners") 47 // empty the connection channel 48 select { 49 case <-m.connection: 50 default: 51 } 52 } 53 m.mutex.Unlock() 54 if connectionCount == 0 { 55 // No listeners so the source can be paused 56 log.Trace("Pausing the eventsource") 57 select { 58 case <-ctx.Done(): 59 break loop 60 case <-m.connection: 61 log.Trace("Connection detected - restarting the eventsource") 62 // OK we're back so lets reset the timer and start again 63 // We won't change the "then" time because there could be concurrency issues 64 select { 65 case <-timer.C: 66 default: 67 } 68 continue 69 } 70 } 71 72 now := timeutil.TimeStampNow().Add(-2) 73 74 uidCounts, err := activities_model.GetUIDsAndNotificationCounts(then, now) 75 if err != nil { 76 log.Error("Unable to get UIDcounts: %v", err) 77 } 78 for _, uidCount := range uidCounts { 79 m.SendMessage(uidCount.UserID, &Event{ 80 Name: "notification-count", 81 Data: uidCount, 82 }) 83 } 84 then = now 85 86 if setting.Service.EnableTimetracking { 87 usersStopwatches, err := issues_model.GetUIDsAndStopwatch() 88 if err != nil { 89 log.Error("Unable to get GetUIDsAndStopwatch: %v", err) 90 return 91 } 92 93 for _, userStopwatches := range usersStopwatches { 94 apiSWs, err := convert.ToStopWatches(userStopwatches.StopWatches) 95 if err != nil { 96 if !issues_model.IsErrIssueNotExist(err) { 97 log.Error("Unable to APIFormat stopwatches: %v", err) 98 } 99 continue 100 } 101 dataBs, err := json.Marshal(apiSWs) 102 if err != nil { 103 log.Error("Unable to marshal stopwatches: %v", err) 104 continue 105 } 106 m.SendMessage(userStopwatches.UserID, &Event{ 107 Name: "stopwatches", 108 Data: string(dataBs), 109 }) 110 } 111 } 112 } 113 } 114 m.UnregisterAll() 115 }