From 976296cd52533ff565407e55e872339cc312a0cf Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Mon, 16 Jan 2017 16:17:44 -0500 Subject: [PATCH 1/4] Fixing performance issue with notifications (#5083) --- api/post.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/api/post.go b/api/post.go index 27a610199f..bdbd32d2ef 100644 --- a/api/post.go +++ b/api/post.go @@ -996,9 +996,11 @@ func sendNotificationEmail(c *Context, post *model.Post, user *model.User, chann "Hour": fmt.Sprintf("%02d", tm.Hour()), "Minute": fmt.Sprintf("%02d", tm.Minute()), "TimeZone": zone, "Month": month, "Day": day})) - if err := utils.SendMail(user.Email, html.UnescapeString(subject), bodyPage.Render()); err != nil { - l4g.Error(utils.T("api.post.send_notifications_and_forget.send.error"), user.Email, err) - } + go func() { + if err := utils.SendMail(user.Email, html.UnescapeString(subject), bodyPage.Render()); err != nil { + l4g.Error(utils.T("api.post.send_notifications_and_forget.send.error"), user.Email, err) + } + }() if einterfaces.GetMetricsInterface() != nil { einterfaces.GetMetricsInterface().IncrementPostSentEmail() @@ -1092,7 +1094,7 @@ func sendPushNotification(post *model.Post, user *model.User, channel *model.Cha for _, session := range sessions { tmpMessage := *model.PushNotificationFromJson(strings.NewReader(msg.ToJson())) tmpMessage.SetDeviceIdAndPlatform(session.DeviceId) - sendToPushProxy(tmpMessage) + go sendToPushProxy(tmpMessage) if einterfaces.GetMetricsInterface() != nil { einterfaces.GetMetricsInterface().IncrementPostSentPush() } @@ -1120,7 +1122,7 @@ func clearPushNotification(userId string, channelId string) { for _, session := range sessions { tmpMessage := *model.PushNotificationFromJson(strings.NewReader(msg.ToJson())) tmpMessage.SetDeviceIdAndPlatform(session.DeviceId) - sendToPushProxy(tmpMessage) + go sendToPushProxy(tmpMessage) } } From dd6fac50f2741ecc8e7e07c42a3e94b37720bd5e Mon Sep 17 00:00:00 2001 From: Harrison Healey Date: Wed, 18 Jan 2017 08:50:01 -0500 Subject: [PATCH 2/4] Removed index on Teams.Description column (#5095) * Removed index on Teams.Description column * Fixed RemoveIndexIfExists when running with MySQL * Fixed RemoveIndexIfExists when running Postgres and added unit tests --- store/sql_store.go | 34 +++++++++++++++++------------ store/sql_store_test.go | 48 +++++++++++++++++++++++++++++++++++++++++ store/sql_team_store.go | 2 +- 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/store/sql_store.go b/store/sql_store.go index 6a852430c4..214bce7208 100644 --- a/store/sql_store.go +++ b/store/sql_store.go @@ -462,19 +462,19 @@ func (ss *SqlStore) AlterColumnTypeIfExists(tableName string, columnName string, return true } -func (ss *SqlStore) CreateUniqueIndexIfNotExists(indexName string, tableName string, columnName string) { - ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_DEFAULT, true) +func (ss *SqlStore) CreateUniqueIndexIfNotExists(indexName string, tableName string, columnName string) bool { + return ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_DEFAULT, true) } -func (ss *SqlStore) CreateIndexIfNotExists(indexName string, tableName string, columnName string) { - ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_DEFAULT, false) +func (ss *SqlStore) CreateIndexIfNotExists(indexName string, tableName string, columnName string) bool { + return ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_DEFAULT, false) } -func (ss *SqlStore) CreateFullTextIndexIfNotExists(indexName string, tableName string, columnName string) { - ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_FULL_TEXT, false) +func (ss *SqlStore) CreateFullTextIndexIfNotExists(indexName string, tableName string, columnName string) bool { + return ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_FULL_TEXT, false) } -func (ss *SqlStore) createIndexIfNotExists(indexName string, tableName string, columnName string, indexType string, unique bool) { +func (ss *SqlStore) createIndexIfNotExists(indexName string, tableName string, columnName string, indexType string, unique bool) bool { uniqueStr := "" if unique { @@ -485,7 +485,7 @@ func (ss *SqlStore) createIndexIfNotExists(indexName string, tableName string, c _, err := ss.GetMaster().SelectStr("SELECT $1::regclass", indexName) // It should fail if the index does not exist if err == nil { - return + return false } query := "" @@ -512,7 +512,7 @@ func (ss *SqlStore) createIndexIfNotExists(indexName string, tableName string, c } if count > 0 { - return + return false } fullTextIndex := "" @@ -531,15 +531,17 @@ func (ss *SqlStore) createIndexIfNotExists(indexName string, tableName string, c time.Sleep(time.Second) os.Exit(EXIT_CREATE_INDEX_MISSING) } + + return true } -func (ss *SqlStore) RemoveIndexIfExists(indexName string, tableName string) { +func (ss *SqlStore) RemoveIndexIfExists(indexName string, tableName string) bool { if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES { _, err := ss.GetMaster().SelectStr("SELECT $1::regclass", indexName) // It should fail if the index does not exist - if err == nil { - return + if err != nil { + return false } _, err = ss.GetMaster().Exec("DROP INDEX " + indexName) @@ -548,6 +550,8 @@ func (ss *SqlStore) RemoveIndexIfExists(indexName string, tableName string) { time.Sleep(time.Second) os.Exit(EXIT_REMOVE_INDEX_POSTGRES) } + + return true } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL { count, err := ss.GetMaster().SelectInt("SELECT COUNT(0) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() and table_name = ? AND index_name = ?", tableName, indexName) @@ -557,8 +561,8 @@ func (ss *SqlStore) RemoveIndexIfExists(indexName string, tableName string) { os.Exit(EXIT_REMOVE_INDEX_MYSQL) } - if count > 0 { - return + if count <= 0 { + return false } _, err = ss.GetMaster().Exec("DROP INDEX " + indexName + " ON " + tableName) @@ -572,6 +576,8 @@ func (ss *SqlStore) RemoveIndexIfExists(indexName string, tableName string) { time.Sleep(time.Second) os.Exit(EXIT_REMOVE_INDEX_MISSING) } + + return true } func IsUniqueConstraintError(err string, indexName []string) bool { diff --git a/store/sql_store_test.go b/store/sql_store_test.go index d65d591ad3..3c6081e3c5 100644 --- a/store/sql_store_test.go +++ b/store/sql_store_test.go @@ -118,3 +118,51 @@ func TestAlertDbCmds(t *testing.T) { t.Fatal("Column should not exist") } } + +func TestCreateIndexIfNotExists(t *testing.T) { + Setup() + + sqlStore := store.(*SqlStore) + + defer sqlStore.RemoveColumnIfExists("Systems", "Test") + if !sqlStore.CreateColumnIfNotExists("Systems", "Test", "VARCHAR(50)", "VARCHAR(50)", "") { + t.Fatal("Failed to create test column") + } + + defer sqlStore.RemoveIndexIfExists("idx_systems_create_index_test", "Systems") + if !sqlStore.CreateIndexIfNotExists("idx_systems_create_index_test", "Systems", "Test") { + t.Fatal("Should've created test index") + } + + if sqlStore.CreateIndexIfNotExists("idx_systems_create_index_test", "Systems", "Test") { + t.Fatal("Shouldn't have created index that already exists") + } +} + +func TestRemoveIndexIfExists(t *testing.T) { + Setup() + + sqlStore := store.(*SqlStore) + + defer sqlStore.RemoveColumnIfExists("Systems", "Test") + if !sqlStore.CreateColumnIfNotExists("Systems", "Test", "VARCHAR(50)", "VARCHAR(50)", "") { + t.Fatal("Failed to create test column") + } + + if sqlStore.RemoveIndexIfExists("idx_systems_remove_index_test", "Systems") { + t.Fatal("Should've failed to remove index that doesn't exist") + } + + defer sqlStore.RemoveIndexIfExists("idx_systems_remove_index_test", "Systems") + if !sqlStore.CreateIndexIfNotExists("idx_systems_remove_index_test", "Systems", "Test") { + t.Fatal("Should've created test index") + } + + if !sqlStore.RemoveIndexIfExists("idx_systems_remove_index_test", "Systems") { + t.Fatal("Should've removed index that exists") + } + + if sqlStore.RemoveIndexIfExists("idx_systems_remove_index_test", "Systems") { + t.Fatal("Should've failed to remove index that was already removed") + } +} diff --git a/store/sql_team_store.go b/store/sql_team_store.go index 023ce8a5ae..85a2d995e7 100644 --- a/store/sql_team_store.go +++ b/store/sql_team_store.go @@ -44,7 +44,7 @@ func NewSqlTeamStore(sqlStore *SqlStore) TeamStore { func (s SqlTeamStore) CreateIndexesIfNotExists() { s.CreateIndexIfNotExists("idx_teams_name", "Teams", "Name") - s.CreateIndexIfNotExists("idx_teams_description", "Teams", "Description") + s.RemoveIndexIfExists("idx_teams_description", "Teams") s.CreateIndexIfNotExists("idx_teams_invite_id", "Teams", "InviteId") s.CreateIndexIfNotExists("idx_teams_update_at", "Teams", "UpdateAt") s.CreateIndexIfNotExists("idx_teams_create_at", "Teams", "CreateAt") From 36b62333b1c5c1322a87a0d2bf3d430b9d88d3c9 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Wed, 18 Jan 2017 16:45:41 -0500 Subject: [PATCH 3/4] Fixing CLI backwards compatibility (#5121) --- cmd/platform/server.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmd/platform/server.go b/cmd/platform/server.go index 51078b6aa5..83185a45fd 100644 --- a/cmd/platform/server.go +++ b/cmd/platform/server.go @@ -37,6 +37,12 @@ func runServerCmd(cmd *cobra.Command, args []string) error { if err != nil { return err } + + // Backwards compatibility with -config flag + if flagConfigFile != "" { + config = flagConfigFile + } + runServer(config) return nil } From 0d8bb03b5773923cf52f4d8cb2711131caae105c Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Thu, 19 Jan 2017 09:58:38 -0500 Subject: [PATCH 4/4] Add functionality for refetching latest data after computer wakes up (#5120) --- webapp/actions/websocket_actions.jsx | 8 +++++++- webapp/routes/route_team.jsx | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/webapp/actions/websocket_actions.jsx b/webapp/actions/websocket_actions.jsx index 9a52eb05c8..1a0ddda630 100644 --- a/webapp/actions/websocket_actions.jsx +++ b/webapp/actions/websocket_actions.jsx @@ -67,9 +67,15 @@ export function close() { WebSocketClient.close(); } -export function reconnect() { +function reconnectWebSocket() { close(); initialize(); +} + +export function reconnect(includeWebSocket = true) { + if (includeWebSocket) { + reconnectWebSocket(); + } if (Client.teamId) { loadChannelsForCurrentUser(); diff --git a/webapp/routes/route_team.jsx b/webapp/routes/route_team.jsx index 4cc85c81b0..fe68324c43 100644 --- a/webapp/routes/route_team.jsx +++ b/webapp/routes/route_team.jsx @@ -8,6 +8,7 @@ import {browserHistory} from 'react-router/es6'; import TeamStore from 'stores/team_store.jsx'; import * as GlobalActions from 'actions/global_actions.jsx'; import {loadStatusesForChannelAndSidebar} from 'actions/status_actions.jsx'; +import {reconnect} from 'actions/websocket_actions.jsx'; import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; import Constants from 'utils/constants.jsx'; const ActionTypes = Constants.ActionTypes; @@ -60,12 +61,28 @@ function doChannelChange(state, replace, callback) { callback(); } +let wakeUpInterval; +let lastTime = (new Date()).getTime(); +const WAKEUP_CHECK_INTERVAL = 30000; // 30 seconds +const WAKEUP_THRESHOLD = 60000; // 60 seconds + function preNeedsTeam(nextState, replace, callback) { if (RouteUtils.checkIfMFARequired(nextState)) { browserHistory.push('/mfa/setup'); return; } + clearInterval(wakeUpInterval); + + wakeUpInterval = setInterval(() => { + const currentTime = (new Date()).getTime(); + if (currentTime > (lastTime + WAKEUP_THRESHOLD)) { // ignore small delays + console.log('computer woke up - fetching latest'); //eslint-disable-line no-console + reconnect(false); + } + lastTime = currentTime; + }, WAKEUP_CHECK_INTERVAL); + // First check to make sure you're in the current team // for the current url. const teamName = nextState.params.team;