Commit graph

4210 commits

Author SHA1 Message Date
Halla Moore
9e2f14513e feat(sync-status): Add messaging in other areas when syncing
Summary:
We want users to know that their account is still syncing if they're
looking for a message and end up at the bottom of a thread list.
This diff changes some of the wording around the messaging when
sync isn't complete and also adds a footer at the bottom of the
syncing thread lists. Additionally, we added a "Show Progress"
link that will expand the sync details in the lower left.

Addresses T7354

Test Plan: tested locally

Reviewers: juan, evan, jackie

Reviewed By: jackie

Differential Revision: https://phab.nylas.com/D3551
2017-01-03 13:27:15 -08:00
Evan Morikawa
0e36afa05e bump(version): 0.5.2 2017-01-03 09:32:59 -08:00
Evan Morikawa
bec35ba82b bump(k2) 2017-01-03 09:32:39 -08:00
Jackie Luo
e03d7b9df6 fix(multi-send): Check that other message exists 2016-12-29 16:00:30 -08:00
Mark Hahnenberg
b99c5a671d fix(startLongConnection) Return the connection
Summary: We weren't doing this which was causing us to deref undefined later.

Test Plan: Run locally

Reviewers: juan, evan

Maniphest Tasks: T7355

Differential Revision: https://phab.nylas.com/D3561
2016-12-27 13:40:39 -08:00
Christine Spang
b1aeefe433 fix(sync-worker): Don't call _determineWorkerPool() twice
A race condition on bootup was causing us to sometimes start
two delta sync workers for the same account.
2016-12-22 12:43:45 -08:00
Evan Morikawa
baa9d7d363 bump(version): 0.5.1 2016-12-22 09:36:07 -08:00
Evan Morikawa
5bde45807a bump(k2) 2016-12-22 09:27:41 -08:00
Evan Morikawa
083021d860 perf(delta): replaces API delta stream with direct in-memory one
Summary:
This replaces the API delta stream with a direct in-memory one

Depends on D3548

Test Plan: manual

Reviewers: halla, jackie

Reviewed By: halla, jackie

Subscribers: juan

Differential Revision: https://phab.nylas.com/D3549
2016-12-21 18:44:17 -08:00
Juan Tejada
a0050a22d5 fix(sync-status):Use weighted percentage avg for sync status progress bar
Summary: Also move calculation to sync store, rename stuff a little bit

Test Plan: Manual :(

Reviewers: evan, jackie, halla

Reviewed By: jackie

Differential Revision: https://phab.nylas.com/D3547
2016-12-21 18:30:54 -05:00
Jackie Luo
b5970e1e46 fix(initial-sync-activity): Update correct function name 2016-12-21 12:04:50 -08:00
Juan Tejada
b29f46fdae fix(auth): Fix authentication notifications
Summary:
Depends on D3544 (K2 diff)

This commit ensures that auth notifications are showed when the
underlying sync worker fails and are cleared when an account is
successfully reconnected

To achieve this, we manually keep track and update syncStates where
appropriate via `Actions.updateAccount`, given that we have access to
N1's version of the account directly from local-sync.
Initially I was considering account delta stream to the cloud-api and the local-api, but that
just complicated things more than it helped.

This commit also fixes a bug with refreshing the gmail token in which we
we were only attempting a token refresh upon restarting the app

This addresses: T7346, T7305, T7335

Test Plan: Manual

Reviewers: halla, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3545
2016-12-21 07:23:09 -05:00
Evan Morikawa
1b75763d91 bump(k2) 2016-12-20 16:47:43 -08:00
Evan Morikawa
487dac31b3 fix(spec): fix asynchronous specs
Summary:
I believe I discovered why our tests intermittently fail, why those
failures cause a cascade of failures, and how to fix it.

The bug is subtle and it's helpful to get a quick refresher on how various
parts of our testing system work:

First a deeper dive into how Promises work:

1. Upon creating a new Promise, the "executor" block (the one that gets
   passed `resolve` and `reject`), gets synchronously run.
2. You eventually call `resolve()`.
3. The minute you call `resolve()`, Bluebird's `async.js` queues up
   whatever's downstream (the next `then` block)
4. The queue gets processed on every "tick".
5. Once the "tick" happens, our queue processes and downstream `then`
   blocks get run.
6. If any more Promises come in before the "tick", they get added to the
   queue. Nothing gets processed until the "tick" happens.

The important takeaway here is this "tick" in step 4. This "tick" is the
core of what makes Promises asynchronous. By default, Bluebird in our
Node-like environment uses `setImmediate` as the underlying
implementation.

Our test environment is different. We do NOT use `setImmediate` in our test
environment.

We use Bluebird's `Promise.setScheduler` API to implement our own "tick".  This
gives us much greater control over when Promises advance. Node's `setImmediate`
puts you at the whim of the underlying event loop.

Before today, our test "tick" implementation used `setTimeout` and
`advanceClock` triggered by `process.nextTick`.

Let me also quickly explain `setTimeout` in our test environment.

We globally override `setTimeout` in our test environment to not be based on
actual time at all. There are places in our code where we wait for several
hundred miliseconds, or have timeouts places. Instead of "sleeping" some amount
of time and hoping for the best, we gain absolute control over "time". "Time"
is just an integer value that only moves forward when you manually call
`advanceClock()` and pass it a certain number of "milliseconds".

At the beginning of each test, we reset time back to zero, we record
setTimeouts that come in, and as advanceClock gets called, we know if we need
to run any of the setTimeout callbacks.

Back to the Promise "tick" implementation. Before today, our testing "tick"
implementation relied our our stubbed `setTimeout` and our control of time.

This almost always works fine. Unfortunately tests would sometimes
intermittently fail, and furthermore cause a cascade of failures down the road.

We've been plauged with this for as long as I can remember. I think I finally
found how all of this comes together to cause these intermittent failures and
how to fix it.

The issue arises from a test like the one in query-subscription-pool-spec.  We
have tests here (and subtly in other yet unknown places) that go
something like this:

```
it("TEST A", () => {
  Foo.add(new Thing())
  expect(Foo._things.length).toBe(1)
})

it("TEST B", () => {
  expect(true).toBe(true)
})
```

At the surface this test looks straightforward. The problem is that
`Foo.add` may down the line call something like `trigger()`, which may
have listeners setup, which might try and asynchronously do all kinds of
things (like read the fs or read/write to the database).

The biggest issue with this is that the test 'finishes' immediately after
that `expect` block and immediately moves onto the next test. If `Foo.add`
is asynchronous, by the time whatever downstream effects of `Foo.add` take
place we may be in a completely different test. Furthremore if those
downstream function errors, those errors will be raised, but Jasmine will
catch them in the wrong test sending you down a rabbit hole of dispair.

It gets worse.

At the start of each test, we reset our `setTimeout` stub time back to
zero. This is problematic when combined with the last issue.

Suppose `Foo.add` ends up queuing a downstream Promsie. Before today, that
downstream Promise used `setTimeout(0)` to trigger the `then` block.

Suppose TEST A finishes before `process.nextTick` in our custom scheduler
can call `advanceClock` and run the downstream Promise.

Once Test B starts, it will reset our `setTimeout` stub time back to zero.

`process.nextTick` comes back after Test B has started and calls
`advanceClock` like it's supposed to.

Unfortunately, because our stub time has been reset, advanceClock will NOT
find the original callback function that would have resolved `Foo.add`'s
downstream Promise!!!

This means that Bluebird is now stuck waiting for a "tick" that will never
come anymore.

Since Bluebird thinks it's waiting for a "tick", all future Promises will
get queued, but never called (see Step 6 of the Promise description
above).

This is why once one test fails, downstream ones never complete and
Jasmine times out.

The failure is intermittent because `process.nextTick` is racing agianst a
test finishing, the next one starting, and how many and how far downstream
promises are setup.

Okay. So how do we fix this? First I tried to simply not reset the time back to
zero again in our stubbed time-override. This doesn't work because it simply
exposes the diasterous consequences of downstream Promises resolving after a
test has completed. When a test completes we cleanup objects, unmount React
components. Those downstream promises and timeouts come back and throw all
kinds of errors like: "can't read property x of undefined" and "can't find a
match for component X".

The fix that works the best is to simply MAKE PROMISES FULLY SYCNRHONOUS.
Now if you look at our custom Promise Test Scheduler in time-override,
you'll see that it immediately and sychronously calls the function. This
means that all downstream promises will run BEFORE the test ends.

Note that this is designed as a safeguard. The best way to make a more
robust test is to declare that your funtion body is asynchronous. If you
call a method that has downstream effects, it's your responsibility to
wait for them to finish. I would consider the test example above a very,
very subtle bug. Unfortunately it's so subtle that it's unreasonable to
expect that we'll always catch them. Making everything in our testing
environment synchronous ensures that test setup and cleanup happen when we
intuitively expect them to.

Addendum:

The full Promise call chain looks something like this:

-> `Promise::_resolveCallback`
-> `Promise::_fulfill`
-> `Promise::_async.settlePromises`
-> `AsyncSettlePromises`
-> `Async::_queueTick`
-> CHECK `Async::_isTickUsed`
-> `Async::_schedule`
-> `TimeOverride.scheduler`
-> `setTimeout`
-> `process.nextTick`
-> `advanceClock`
-> `Async::_drainQueues`
-> `Async::_drainQueue`
-> `THEN BLOCK RUNS`
-> `Maybe more things get added to queue`
-> `Async::_reset`
-> `Async::_queueTick` works again.

Test Plan: They now work

Reviewers: halla, mark, spang, juan, jackie

Reviewed By: juan, jackie

Differential Revision: https://phab.nylas.com/D3538
2016-12-20 16:47:26 -08:00
Evan Morikawa
7f36d2b4b2 bump(k2) 2016-12-20 13:08:50 -08:00
Juan Tejada
454676581a fix(sync-status) Fix off by one error in store 2016-12-20 08:25:20 -08:00
Halla Moore
78d1b85c7f re-feat(initial-sync-status): Bring the intiial sync progress bar back
Summary:
Adds a UI component to see the progress of initial sync.
(The behavior is sometimes a little strange, but I believe this is
just because of weird behavior in the NylasSyncStatusStore itself.
For instance, it sometimes never populates the `folderSyncProgress`
fields, or it never sets the progress to 1, so the bar stops at 99%)

Test Plan: tested locally

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3536
2016-12-19 12:40:36 -08:00
Juan Tejada
0f30121c3f fix(send) Fix typo in ReconcileMultiSendTask 2016-12-19 10:09:15 -08:00
Evan Morikawa
fd8949e9f2 bump(version): 0.5.0 2016-12-19 09:35:21 -08:00
Evan Morikawa
6ce89426e2 bump(k2) 2016-12-19 09:25:13 -08:00
Evan Morikawa
bbaf4590af feat(auth): update onboarding helpers to be async 2016-12-18 23:38:34 -05:00
Evan Morikawa
c95107f336 bump(k2) 2016-12-16 18:51:27 -05:00
Halla Moore
7d7fce2f8e fix(sending): Check if failedRecipients exists before checking length 2016-12-16 15:46:52 -08:00
Juan Tejada
44d7edaed6 feat(k2): Ensure send runs fast, clean up multisend tasks
Summary:
Associated K2 diff: D3529

This commit converts multi-send from a 3 step process into a 2 step
process

The first step creates the base message and sends a message per
recipient, each with its customized message body for tracking.

The second step reconciles all sent messages, specifically removing any
sent messages created by gmail, and saving the correct message to the
sent folder

This commit also ensures that we run the send tasks immediately by
ensuring we restart the sync loop if its already running

Depends on D3529

Test Plan: Manual

Reviewers: evan, jackie, halla

Reviewed By: jackie, halla

Differential Revision: https://phab.nylas.com/D3530
2016-12-16 14:45:20 -08:00
Evan Morikawa
17536ca660 bump(k2) 2016-12-16 17:42:03 -05:00
Evan Morikawa
31a8fb2b5b feat(auth): add office 365 support
Summary: Adds a new button in auth for native Office 365 support

Test Plan: manual

Reviewers: jackie, halla, mark, juan

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D3532
2016-12-16 16:53:46 -05:00
Evan Morikawa
1f5531bd08 fix(sync): fix sync status store 2016-12-16 16:44:13 -05:00
Halla Moore
2441db6546 fix(draft-store): Don't pop up a draft before it exists in the session
Summary:
The composer wasn't popping out correctly because the session's draft
was still null. This diff switches to using sessionForClientId(),
even if the session already exists in _draftSessions, because
sessionForClientId() won't create a new session if it doesn't need
to, and will always return a promise that resolves once the session
gets its draft. This promise will resolve immediately if the session
already has a draft.

Test Plan: tested locally

Reviewers: evan, juan

Reviewed By: juan

Subscribers: juan, spang

Differential Revision: https://phab.nylas.com/D3531
2016-12-16 13:24:29 -08:00
Karim Hamidou
cb6f761df3 Required changes for refreshing access tokens. 2016-12-16 11:10:20 -08:00
Evan Morikawa
f34a8f8f0a feat(babel): bump local babel and update K2 to use babel toolchain 2016-12-16 13:08:52 -05:00
Christine Spang
37e691d329 bump(K2) 2016-12-15 18:55:33 -08:00
Christine Spang
baa5fde8d3 fix(quote-parser): Restore still relevant comment I actually removed
At one point I considered just removing this feature entirely,
but ended up not.
2016-12-15 18:43:08 -08:00
Christine Spang
63a95c2096 fix(rendering): Fix quote stripping of many plaintext emails
Summary:
Since we changed the way we mark up plaintext emails to wrap them in <pre>
tags, the quote stripper has been failing to restore bodies in the cases
where a plaintext email starts with an inline quote (and thus the whole
contents of the <pre> tag is detected as a quote string).

This diff also fixes the HTML sanitizer to not strip off our custom
"nylas-plaintext" class, which isn't currently used for anything but
allows us to definitively know which tags we added on for marking up
plaintext. Might be useful at some point!

Test Plan: unit test included, manual inspection of message display

Reviewers: evan

Differential Revision: https://phab.nylas.com/D3519
2016-12-15 18:40:34 -08:00
Evan Morikawa
f7491d7e7b bump(bluebird): upgrade bluebird
Summary:
I upgraded bluebird because I thought there was some missing dependency
issue when I booted K2. It actually turned out that the issue was missing
`striptags` require in the K2 local-sync package json and had nothing to
do with Bluebird.

But since were here and about to QA I figured I might as well bump it
anyway. Especially since I'll need it later to better diagnose async
tests.

I carefully went through the 3.0 changelog and believe I fixed the
outstanding issues

Test Plan: manual

Reviewers: juan

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D3523
2016-12-15 17:33:37 -05:00
Halla Moore
d03049b403 fix(mail-rules): use the right field name to get an account id
Summary:
With the fix to the delta-processor, this is all that's needed to
get mail rules working! Some places were trying to use 'accountId'
to access an account object's id, but it needs to be 'id' instead.

Test Plan: tested locally

Reviewers: jackie

Reviewed By: jackie

Differential Revision: https://phab.nylas.com/D3525
2016-12-15 14:18:50 -08:00
Evan Morikawa
99b428f90c fix(import): require 'rx' from 'nylas-exports' 2016-12-15 15:32:47 -05:00
Halla Moore
9066078911 fix(delta-processor): Return created models in the expected format
Summary:
We were returning an array of arrays, when really we wanted an object
of arrays keyed by model type. This also involved removing an implementation
of mapObject that was overwriting underscore's implementation of it.

Test Plan: local, having others try it.

Reviewers: juan

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D3509
2016-12-15 12:12:37 -08:00
Juan Tejada
9039c49dba fix(send/tasks): Fix deltas for SyncbackRequest SyncbackTaskAPIRequest
Summary:
This commit fixes processing deltas for `ProviderSyncbackRequests` and
resolution of the `SyncbackTaskAPIRequest`

Specifically:
- Fix and update field definitions for `ProviderSyncbackRequest`
- Correctly parse the error attached to any `ProviderSyncbackRequest`
- Correctly process deltas for `ProviderSyncbackRequests` inside the
delta-processor
- Fix any tasks that used `SyncbackTaskAPIRequest`, and update send to use those

Depends on D3510

Test Plan: Todo/Manual

Reviewers: jackie, halla, evan

Reviewed By: halla, evan

Differential Revision: https://phab.nylas.com/D3511
2016-12-15 11:57:14 -08:00
Juan Tejada
d92506d8f1 fix(sync-status): Change old per model status, in favor of per folder
Summary:
Addresses T7275
Previously, we kept track of the sync status of each API model, and the progress
we'd made syncing all available models (e.g. all threads, messages, events, etc)

Given K2's set up, we are now keeping track of sync status per folder, i.e. what
percent of the folder's messages we've synced. This status is now reported from K2
to N1 via folder object deltas, and this commit rewrites the
NylasSyncStatusStore (in ES6) to reflect that.

The new Store keeps the sync state per account, which is the merged state of
per folder sync state, and delta connections state.
We also got rid of `CategoryStore.whenCategoriesReady` in favor of
`whenCategoryListSynced`, which is derived from the fact hat as long as we've
started syncing one folder, we've already synced the entire list of of folders/labels.

There are a couple of TODOs to be addressed in upcoming diffs:
- T7329 Restore the sidebar component to show sync progress, which was previously removed
- T7330 Figure out how to report sync progress per label, specifically, we are interested in knowing how much of the inbox we've synced, which is a label in Gmail. (This might be a non-issue if we sync the inbox very fast, first)

Depends on D3514

Test Plan: Manual

Reviewers: mark, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3515
2016-12-15 11:17:20 -08:00
Juan Tejada
2457da3708 Bump submodule 2016-12-15 11:10:44 -08:00
Evan Morikawa
dd2acf4b74 bump(electron): to 1.4.12 from 1.4.5 2016-12-15 13:24:28 -05:00
Evan Morikawa
d1c587a01c fix(spec): add support for async specs and disable misbehaving ones
More spec fixes

replace process.nextTick with setTimeout(fn, 0) for specs

Also added an unspy in the afterEach

Temporarily disable specs

fix(spec): start fixing specs

Summary:
This is the WIP fix to our spec runner.

Several tests have been completely commented out that will require
substantially more work to fix. These have been added to our sprint
backlog.

Other tests have been fixed to update to new APIs or to deal with genuine
bugs that were introduced without our knowing!

The most common non-trivial change relates to observing the `NylasAPI` and
`NylasAPIRequest`. We used to observe the arguments to `makeRequest`.
Unfortunately `NylasAPIRequest.run` is argumentless. Instead you can do:
`NylasAPIRequest.prototype.run.mostRecentCall.object.options` to get the
`options` passed into the object. the `.object` property grabs the context
of the spy when it was last called.

Fixing these tests uncovered several concerning issues with our test
runner. I spent a while tracking down why our participant-text-field-spec
was failling every so often. I chose that spec because it was the first
spec to likely fail, thereby requiring looking at the least number of
preceding files. I tried binary searching, turning on and off, several
files beforehand only to realize that the failure rate was not determined
by a particular preceding test, but rather the existing and quantity of
preceding tests, AND the number of console.log statements I had. There is
some processor-dependent race condition going on that needs further
investigation.

I also discovered an issue with the file-download-spec. We were getting
errors about it accessing a file, which was very suspicious given the code
stubs out all fs access. This was caused due to a spec that called an
async function outside ot a `waitsForPromise` block or a `waitsFor` block.
The test completed, the spies were cleaned up, but the downstream async
chain was still running. By the time the async chain finished the runner
was already working on the next spec and the spies had been restored
(causing the real fs access to run).

Juan had an idea to kill the specs once one fails to prevent cascading
failures. I'll implement this in the next diff update

Test Plan: npm test

Reviewers: juan, halla, jackie

Differential Revision: https://phab.nylas.com/D3501

Disable other specs

Disable more broken specs

All specs turned off till passing state

Use async-safe versions of spec functions

Add async test spec

Remove unused package code

Remove canary spec
2016-12-15 13:02:00 -05:00
Christine Spang
1f2b162d0a fix(rendering): Don't set a class on plaintext pre wrapping
Our HTML sanitizer that we run bodies through before rendering
strips off this class, so it's not currently working with the
class set. Since this CSS is specific to the email frame, should
be OK to have no class at all.
2016-12-14 20:35:51 -08:00
Halla Moore
ace6cf4c9e feat(showDetails): Allow a "Show Details" option on error dialogs
Summary:
Pass in more details on sending errors, so that they can be viewed
more easily by clicking "Show Details", rather than having to check
the worker window console.

Test Plan: tested locally

Reviewers: evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3505
2016-12-14 13:02:18 -08:00
Juan Tejada
9b9df21c93 fix(script/bootstrap) Properly remove already present lns + error handling 2016-12-13 17:57:54 -08:00
Jackie Luo
cb9802daf2 fix(tracking): Update server URLs and send MESSAGE_ID 2016-12-13 12:54:25 -08:00
Evan Morikawa
41c893cc17 Move old edgehill src/pro into K2/packages/nylas-private
Summary:
feat(bootstrap): automatically init submodule if able

fix(bootstrap): symlink arc instead of copy

Test Plan: test

Reviewers: juan

Differential Revision: https://phab.nylas.com/D3494
2016-12-12 10:38:43 -05:00
Evan Morikawa
eb7f3c90e6 feat(bootstrap): automatically init submodule if able 2016-12-12 10:22:40 -05:00
Evan Morikawa
2650613ef1 Move old edgehill src/pro into K2/packages/nylas-private 2016-12-12 10:10:26 -05:00
Evan Morikawa
9cf05c780e bump(k2) 2016-12-09 11:15:38 -08:00