From 97558f6a6ec4c53fa69035fb430ead209d9c222d Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Fri, 13 Jan 2017 13:53:37 -0500 Subject: PLT-4938 Add app package and move logic over from api package (#4931) * Add app package and move logic over from api package * Change app package functions to return errors * Move non-api tests into app package * Fix merge --- api/status.go | 257 ++-------------------------------------------------------- 1 file changed, 7 insertions(+), 250 deletions(-) (limited to 'api/status.go') diff --git a/api/status.go b/api/status.go index 909ab50ec..69f391f47 100644 --- a/api/status.go +++ b/api/status.go @@ -8,67 +8,30 @@ import ( l4g "github.com/alecthomas/log4go" - "github.com/mattermost/platform/einterfaces" + "github.com/mattermost/platform/app" "github.com/mattermost/platform/model" - "github.com/mattermost/platform/store" "github.com/mattermost/platform/utils" ) -var statusCache *utils.Cache = utils.NewLru(model.STATUS_CACHE_SIZE) - -func ClearStatusCache() { - statusCache.Purge() -} - -func AddStatusCacheSkipClusterSend(status *model.Status) { - statusCache.Add(status.UserId, status) -} - -func AddStatusCache(status *model.Status) { - AddStatusCacheSkipClusterSend(status) - - if einterfaces.GetClusterInterface() != nil { - einterfaces.GetClusterInterface().UpdateStatus(status) - } -} - func InitStatus() { l4g.Debug(utils.T("api.status.init.debug")) BaseRoutes.Users.Handle("/status", ApiUserRequired(getStatusesHttp)).Methods("GET") BaseRoutes.Users.Handle("/status/ids", ApiUserRequired(getStatusesByIdsHttp)).Methods("POST") - BaseRoutes.WebSocket.Handle("get_statuses", ApiWebSocketHandler(getStatusesWebSocket)) - BaseRoutes.WebSocket.Handle("get_statuses_by_ids", ApiWebSocketHandler(getStatusesByIdsWebSocket)) + app.Srv.WebSocketRouter.Handle("get_statuses", ApiWebSocketHandler(getStatusesWebSocket)) + app.Srv.WebSocketRouter.Handle("get_statuses_by_ids", ApiWebSocketHandler(getStatusesByIdsWebSocket)) } func getStatusesHttp(c *Context, w http.ResponseWriter, r *http.Request) { - statusMap := model.StatusMapToInterfaceMap(GetAllStatuses()) + statusMap := model.StatusMapToInterfaceMap(app.GetAllStatuses()) w.Write([]byte(model.StringInterfaceToJson(statusMap))) } func getStatusesWebSocket(req *model.WebSocketRequest) (map[string]interface{}, *model.AppError) { - statusMap := GetAllStatuses() + statusMap := app.GetAllStatuses() return model.StatusMapToInterfaceMap(statusMap), nil } -func GetAllStatuses() map[string]*model.Status { - userIds := statusCache.Keys() - statusMap := map[string]*model.Status{} - - for _, userId := range userIds { - if id, ok := userId.(string); !ok { - continue - } else { - status := GetStatusFromCache(id) - if status != nil { - statusMap[id] = status - } - } - } - - return statusMap -} - func getStatusesByIdsHttp(c *Context, w http.ResponseWriter, r *http.Request) { userIds := model.ArrayFromJson(r.Body) @@ -77,7 +40,7 @@ func getStatusesByIdsHttp(c *Context, w http.ResponseWriter, r *http.Request) { return } - statusMap, err := GetStatusesByIds(userIds) + statusMap, err := app.GetStatusesByIds(userIds) if err != nil { c.Err = err return @@ -93,216 +56,10 @@ func getStatusesByIdsWebSocket(req *model.WebSocketRequest) (map[string]interfac return nil, NewInvalidWebSocketParamError(req.Action, "user_ids") } - statusMap, err := GetStatusesByIds(userIds) + statusMap, err := app.GetStatusesByIds(userIds) if err != nil { return nil, err } return statusMap, nil } - -func GetStatusesByIds(userIds []string) (map[string]interface{}, *model.AppError) { - statusMap := map[string]interface{}{} - metrics := einterfaces.GetMetricsInterface() - - missingUserIds := []string{} - for _, userId := range userIds { - if result, ok := statusCache.Get(userId); ok { - statusMap[userId] = result.(*model.Status).Status - if metrics != nil { - metrics.IncrementMemCacheHitCounter("Status") - } - } else { - missingUserIds = append(missingUserIds, userId) - if metrics != nil { - metrics.IncrementMemCacheMissCounter("Status") - } - } - } - - if len(missingUserIds) > 0 { - if result := <-Srv.Store.Status().GetByIds(missingUserIds); result.Err != nil { - return nil, result.Err - } else { - statuses := result.Data.([]*model.Status) - - for _, s := range statuses { - AddStatusCache(s) - statusMap[s.UserId] = s.Status - } - } - } - - // For the case where the user does not have a row in the Status table and cache - for _, userId := range missingUserIds { - if _, ok := statusMap[userId]; !ok { - statusMap[userId] = model.STATUS_OFFLINE - } - } - - return statusMap, nil -} - -func SetStatusOnline(userId string, sessionId string, manual bool) { - broadcast := false - - var oldStatus string = model.STATUS_OFFLINE - var oldTime int64 = 0 - var oldManual bool = false - var status *model.Status - var err *model.AppError - - if status, err = GetStatus(userId); err != nil { - status = &model.Status{userId, model.STATUS_ONLINE, false, model.GetMillis(), ""} - broadcast = true - } else { - if status.Manual && !manual { - return // manually set status always overrides non-manual one - } - - if status.Status != model.STATUS_ONLINE { - broadcast = true - } - - oldStatus = status.Status - oldTime = status.LastActivityAt - oldManual = status.Manual - - status.Status = model.STATUS_ONLINE - status.Manual = false // for "online" there's no manual setting - status.LastActivityAt = model.GetMillis() - } - - AddStatusCache(status) - - // Only update the database if the status has changed, the status has been manually set, - // or enough time has passed since the previous action - if status.Status != oldStatus || status.Manual != oldManual || status.LastActivityAt-oldTime > model.STATUS_MIN_UPDATE_TIME { - achan := Srv.Store.Session().UpdateLastActivityAt(sessionId, status.LastActivityAt) - - var schan store.StoreChannel - if broadcast { - schan = Srv.Store.Status().SaveOrUpdate(status) - } else { - schan = Srv.Store.Status().UpdateLastActivityAt(status.UserId, status.LastActivityAt) - } - - if result := <-achan; result.Err != nil { - l4g.Error(utils.T("api.status.last_activity.error"), userId, sessionId, result.Err) - } - - if result := <-schan; result.Err != nil { - l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) - } - } - - if broadcast { - event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil) - event.Add("status", model.STATUS_ONLINE) - event.Add("user_id", status.UserId) - go Publish(event) - } -} - -func SetStatusOffline(userId string, manual bool) { - status, err := GetStatus(userId) - if err == nil && status.Manual && !manual { - return // manually set status always overrides non-manual one - } - - status = &model.Status{userId, model.STATUS_OFFLINE, manual, model.GetMillis(), ""} - - AddStatusCache(status) - - if result := <-Srv.Store.Status().SaveOrUpdate(status); result.Err != nil { - l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) - } - - event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil) - event.Add("status", model.STATUS_OFFLINE) - event.Add("user_id", status.UserId) - go Publish(event) -} - -func SetStatusAwayIfNeeded(userId string, manual bool) { - status, err := GetStatus(userId) - - if err != nil { - status = &model.Status{userId, model.STATUS_OFFLINE, manual, 0, ""} - } - - if !manual && status.Manual { - return // manually set status always overrides non-manual one - } - - if !manual { - if status.Status == model.STATUS_AWAY { - return - } - - if !IsUserAway(status.LastActivityAt) { - return - } - } - - status.Status = model.STATUS_AWAY - status.Manual = manual - status.ActiveChannel = "" - - AddStatusCache(status) - - if result := <-Srv.Store.Status().SaveOrUpdate(status); result.Err != nil { - l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) - } - - event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil) - event.Add("status", model.STATUS_AWAY) - event.Add("user_id", status.UserId) - go Publish(event) -} - -func GetStatusFromCache(userId string) *model.Status { - if result, ok := statusCache.Get(userId); ok { - status := result.(*model.Status) - statusCopy := &model.Status{} - *statusCopy = *status - return statusCopy - } - - return nil -} - -func GetStatus(userId string) (*model.Status, *model.AppError) { - status := GetStatusFromCache(userId) - if status != nil { - return status, nil - } - - if result := <-Srv.Store.Status().Get(userId); result.Err != nil { - return nil, result.Err - } else { - return result.Data.(*model.Status), nil - } -} - -func IsUserAway(lastActivityAt int64) bool { - return model.GetMillis()-lastActivityAt >= *utils.Cfg.TeamSettings.UserStatusAwayTimeout*1000 -} - -func DoesStatusAllowPushNotification(user *model.User, status *model.Status, channelId string) bool { - props := user.NotifyProps - - if props["push"] == "none" { - return false - } - - if pushStatus, ok := props["push_status"]; (pushStatus == model.STATUS_ONLINE || !ok) && (status.ActiveChannel != channelId || model.GetMillis()-status.LastActivityAt > model.STATUS_CHANNEL_TIMEOUT) { - return true - } else if pushStatus == model.STATUS_AWAY && (status.Status == model.STATUS_AWAY || status.Status == model.STATUS_OFFLINE) { - return true - } else if pushStatus == model.STATUS_OFFLINE && status.Status == model.STATUS_OFFLINE { - return true - } - - return false -} -- cgit v1.2.3-1-g7c22