Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit d60a23c

Browse files
committed
[client-app] (deltas P6) Split local and cloud deltas
Summary: This commit splits apart the `AccountDeltaConnection` class, which was in charge of listening to both cloud /and/ local deltas by way of an artificial interface, `DeltaStreamingInMemoryConnection`. Splitting this into 2 modules with separate responsibilities will hopefully make this code easier to reason about and reduce some cruft and unnecessary indirection. Specifically, this commit makes it so: - `DeltaConnectionManager` is only in charge of starting and ending `DeltaStreamingConnection`s, which are solely in charge of listening to deltas from the cloud api - `LocalSyncDeltaEmitter` no longer unnecessarily emits events for the `deltas` package to listen to but rather directly processes and saves those deltas from the K2 db to edgehill.db - `LocalSyncDeltaEmitter` is also in charge of keeping track of the latest received cursor, under its own JSONBlob key in edgehill.db. This migrates localSync cursors saved under the old key. - `LocalSyncDeltaEmitter` is now instantiated and managed from within the `SyncProcessManager` as opposed to the `SyncWorker`. Apart from removing extra state from the `SyncWorker`, this removes dependencies on the client-app environment from the sync-worker. - `DeltaStreamingInMemoryConnection` and `AccountDeltaConnection` are now gone (Sorry for the big diff! This one was a little hard to split up without landing something broken) Depends on D4121 Test Plan: manual + unit tests planned in upcoming diff Reviewers: halla, mark, evan, spang Reviewed By: evan Differential Revision: https://phab.nylas.com/D4122
1 parent 049a3c2 commit d60a23c

File tree

8 files changed

+141
-281
lines changed

8 files changed

+141
-281
lines changed

packages/client-app/internal_packages/deltas/lib/account-delta-connection.es6

Lines changed: 0 additions & 142 deletions
This file was deleted.

packages/client-app/internal_packages/deltas/lib/delta-connection-store.es6

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import _ from 'underscore';
22
import {AccountStore} from 'nylas-exports'
3-
import AccountDeltaConnection from './account-delta-connection';
3+
import DeltaStreamingConnection from './delta-streaming-connection';
44

55

66
class DeltaConnectionStore {
77
constructor() {
8-
this._accountConnections = [];
8+
this._connections = [];
99
this._unsubscribe = () => {}
1010
}
1111

@@ -18,10 +18,6 @@ class DeltaConnectionStore {
1818
this._unsubscribe()
1919
}
2020

21-
_existingConnectionsForAccount(account) {
22-
return _.find(this._accountConnections, c => c.account().id === account.id);
23-
}
24-
2521
async _ensureConnections() {
2622
if (NylasEnv.inSpecMode()) { return; }
2723

@@ -33,25 +29,27 @@ class DeltaConnectionStore {
3329
this._isBuildingDeltaConnections = true;
3430

3531
try {
36-
const originalConnections = this._accountConnections;
37-
const currentConnections = []
32+
const currentConnections = this._connections;
33+
const nextConnections = []
3834
for (const account of AccountStore.accounts()) {
39-
const existingDeltaConnection = this._existingConnectionsForAccount(account)
40-
if (existingDeltaConnection) {
41-
currentConnections.push(existingDeltaConnection);
35+
const existingConnection = (
36+
currentConnections
37+
.find(conn => conn.account().id === account.id)
38+
)
39+
if (existingConnection) {
40+
nextConnections.push(existingConnection);
4241
continue
4342
}
4443

45-
const newDeltaConnection = new AccountDeltaConnection(account);
46-
await newDeltaConnection.loadStateFromDatabase()
47-
newDeltaConnection.start()
48-
currentConnections.push(newDeltaConnection);
44+
const newDeltaConnection = new DeltaStreamingConnection(account);
45+
await newDeltaConnection.start()
46+
nextConnections.push(newDeltaConnection);
4947
}
50-
const oldDeltaConnections = _.difference(originalConnections, currentConnections);
48+
const oldDeltaConnections = _.difference(currentConnections, nextConnections);
5149
for (const deltaConnection of oldDeltaConnections) {
5250
deltaConnection.end()
5351
}
54-
this._accountConnections = currentConnections;
52+
this._connections = nextConnections;
5553
} finally {
5654
this._isBuildingDeltaConnections = false;
5755
}

packages/client-app/internal_packages/deltas/lib/delta-streaming-connection.es6

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const BASE_RETRY_DELAY = 1000;
1818
class DeltaStreamingConnection {
1919
constructor(account) {
2020
this._account = account
21-
this._state = {cursor: null, status: null}
21+
this._state = null
2222
this._longConnection = null
2323
this._writeStateDebounced = _.debounce(this._writeState, 100)
2424
this._unsubscribers = []
@@ -33,8 +33,15 @@ class DeltaStreamingConnection {
3333
}
3434
}
3535

36-
start() {
36+
account() {
37+
return this._account
38+
}
39+
40+
async start() {
3741
try {
42+
if (!this._state) {
43+
this._state = await this._loadState()
44+
}
3845
const {cursor = 0} = this._state
3946
this._longConnection = new NylasLongConnection({
4047
api: N1CloudAPI,
@@ -70,28 +77,11 @@ class DeltaStreamingConnection {
7077
}
7178

7279
end() {
80+
this._state = null
7381
this._disposeListeners()
7482
this._longConnection.end()
7583
}
7684

77-
async loadStateFromDatabase() {
78-
let json = await DatabaseStore.findJSONBlob(`DeltaStreamingConnectionStatus:${this._account.id}`)
79-
80-
if (!json) {
81-
// Migrate from old storage key
82-
const oldState = await DatabaseStore.findJSONBlob(`NylasSyncWorker:${this._account.id}`)
83-
if (!oldState) { return; }
84-
const {deltaCursors = {}, deltaStatus = {}} = oldState
85-
json = {
86-
cursor: deltaCursors.n1Cloud || null,
87-
status: deltaStatus.n1Cloud || null,
88-
}
89-
}
90-
91-
if (!json) { return }
92-
this._state = json;
93-
}
94-
9585
_setupListeners() {
9686
this._unsubscribers = [
9787
Actions.retryDeltaConnection.listen(this.restart, this),
@@ -104,17 +94,6 @@ class DeltaStreamingConnection {
10494
this._unsubscribers = []
10595
}
10696

107-
_writeState() {
108-
return DatabaseStore.inTransaction(t =>
109-
t.persistJSONBlob(`DeltaStreamingConnectionStatus:${this._account.id}`, this._state)
110-
);
111-
}
112-
113-
_setCursor = (cursor) => {
114-
this._state.cursor = cursor;
115-
this._writeStateDebounced();
116-
}
117-
11897
_onOnlineStatusChanged = () => {
11998
if (OnlineStatusStore.isOnline()) {
12099
this.restart()
@@ -175,6 +154,38 @@ class DeltaStreamingConnection {
175154

176155
setTimeout(() => this.restart(), this._backoffScheduler.nextDelay());
177156
}
157+
158+
_setCursor = (cursor) => {
159+
this._state.cursor = cursor;
160+
this._writeStateDebounced();
161+
}
162+
163+
async _loadState() {
164+
const json = await DatabaseStore.findJSONBlob(`DeltaStreamingConnectionStatus:${this._account.id}`)
165+
if (json) {
166+
return json
167+
}
168+
169+
// Migrate from old storage key
170+
const oldState = await DatabaseStore.findJSONBlob(`NylasSyncWorker:${this._account.id}`)
171+
if (!oldState) {
172+
return {cursor: null, status: null};
173+
}
174+
175+
const {deltaCursors = {}, deltaStatus = {}} = oldState
176+
return {
177+
cursor: deltaCursors.n1Cloud,
178+
status: deltaStatus.n1Cloud,
179+
}
180+
}
181+
182+
async _writeState() {
183+
if (!this._state) { return }
184+
await DatabaseStore.inTransaction(t =>
185+
t.persistJSONBlob(`DeltaStreamingConnectionStatus:${this._account.id}`, this._state)
186+
);
187+
}
188+
178189
}
179190

180191
export default DeltaStreamingConnection

packages/client-app/internal_packages/deltas/lib/delta-streaming-in-memory-connection.es6

Lines changed: 0 additions & 52 deletions
This file was deleted.

packages/client-app/src/nylas-env.es6

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ export default class NylasEnvConstructor {
226226

227227
this.timer = remote.getGlobal('application').timer;
228228

229-
this.localSyncEmitter = new Emitter();
229+
this.globalWindowEmitter = new Emitter();
230230

231231
if (!this.inSpecMode()) {
232232
this.actionBridge = new ActionBridge(ipcRenderer);

0 commit comments

Comments
 (0)