Commit graph

716 commits

Author SHA1 Message Date
Juan Tejada 1c37a8b788 [local-sync] Cleanup sync tasks to be more consistent with syncback tasks
Summary: While working on separating send out of the sync loop, I realized sync tasks could use some cleanup to be more consistent with how we implemented syncback tasks. I reorganized and renamed things a little bit. This will also help us move in the direction of the scheduler implementation under which everything is a task.

Test Plan: manual

Reviewers: evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3660
2017-01-13 12:30:43 -08:00
Halla Moore 30037f915d [local-sync] Add oldestProcessedDate to Folder.syncState
Summary:
Only updated within month precision. We can use this to show how
far back a folder has been synced.

Test Plan: tested locally

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3662
2017-01-13 12:05:45 -08:00
Evan Morikawa e197de86e0 [local-sync] fix attribute scanning in sync worker
Summary:
Fixes https://phab.nylas.com/T7435

The old deepScan (now `scanForAttributeChanges`) and shallowScan (now
`fetchLatestAttributeChanges`) had some fatal flaws.

If you deep scanned it would attempt to load the message attributes of all
messages ever and cause very bad memory leaks.

Also, if you left a mailbox running for a long time, there was a query
that would eventually run `Message.findAll` and, even though it was just
returning the headers, would still run insanely expensive operations

This fixes (and renames) these issues.

Test Plan: manual

Reviewers: spang, halla, juan

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D3657
2017-01-13 12:00:45 -08:00
Christine Spang 7c8146f81b [local-sync] Fix parsing of existing messages derp 2017-01-13 11:15:24 -08:00
Christine Spang a23813a11c [local-sync] For generic IMAP, Thread based on Message-Id, In-Reply-To & References
Summary:
This swaps out our generic IMAP threading mechanism to use the threading
headers on the message instead of the prior way of grouping by subject
and then differentiating based on participants, as that design was
somewhat driven by what we could accomplish easily given legacy data
schema decisions and has serious caveats, such as different threads between
the same people with the same subject being misthreaded together. With K2, we
have free reign to change the data format, so we can do it right.

The algorithm is super simple:
- Define "references" as the union of the Message-Id, In-Reply-To, and
References headers on a message, filtered for valid RFC2822 Message-IDs
- On message sync, if any element of the new message's references
matches any element of an existing message's references, thread them
together

In order to accomplish this, we need to store References in a way that
allows each element to be indexed for fast lookup. That meant either
using the sqlite JSON1 extension + expression-based indices, or creating
a new table. I chose the latter as a time-tested and simple solution,
since we don't need the flexibility of JSON here.

Test Plan: manual - unit tests coming

Reviewers: khamidou, evan, juan

Reviewed By: evan, juan

Differential Revision: https://phab.nylas.com/D3651
2017-01-13 10:39:54 -08:00
Christine Spang 0dcbcee06c [local-sync] Messages generated for send should not be unread 2017-01-13 07:46:18 -08:00
Christine Spang 99309f9c69 [isomorphic-core] Disable nodemailer's automatic X-Mailer header
Examined the headers on a message we sent and found this:
> X-Mailer: nodemailer (2.5.0; +http://nodemailer.com/; SMTP/2.6.0[client:2.8.0])

No need to plaster which sendmail library we're using all over every
email our users send. Turn it off!
2017-01-12 14:16:47 -08:00
Juan Tejada 238b79d06c [local-sync] Don't sync spam until everything else is synced
Summary: Addresses T7426

Test Plan: manual

Reviewers: evan, spang

Reviewed By: spang

Differential Revision: https://phab.nylas.com/D3655
2017-01-12 13:53:17 -08:00
Mark Hahnenberg 59b5961a6c [syncback] Reuse currently open box if possible
Summary:
Previously we would unconditionally issue a SELECT when openBox was
called. Now we check if the currently open box is the one we want first and
return immediately if it is, avoiding the unnecessary SELECT (which can be
quite expensive on large folders like INBOX). We were also calling closeBox
after iterating all the messages in a thread to mark them as read/unread.
This was unnecessary and was causing extra SELECTs to be issued. Now we don't!
This diff is a 5x speedup over the old behavior when marking lots of
threads in the same folder as read all at once.

Test Plan: Run locally, measure perf with log statements

Reviewers: evan, juan

Reviewed By: evan, juan

Differential Revision: https://phab.nylas.com/D3654
2017-01-12 13:16:07 -08:00
Mark Hahnenberg 6a03bbe73f [local-sync] Fix error thrown when Gmail returns no search results
Summary:
We were returning the wrong type in the case that we got no messages
back from the Gmail search API.

Test Plan: Run locally

Reviewers: evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3646
2017-01-12 11:57:07 -08:00
Jackie Luo 21049b2a1f Update Nylas N1 to Nylas Mail
Test Plan: Tested locally.

Reviewers: juan, evan

Reviewed By: juan, evan

Differential Revision: https://phab.nylas.com/D3644
2017-01-12 11:25:39 -08:00
Juan Tejada ab7f994fef [local-sync] Ensure we get new mail ASAP via dedicated imap conn
Summary:
Add a new dedicated imap connection to listen for any updates or new mail on the inbox.
Previously, we wouldn't be able to receive new mail events on the inbox during the sync loop
because other mailboxes would be open while we sync them. This would cause big
delays in receiving new mail, especially if you have a lot of folders

Test Plan: manual

Reviewers: spang, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3650
2017-01-12 11:16:53 -08:00
Halla Moore 914d69557d [iso-core]: Make sure deltaStreamBuilder passes along delete deltas
Summary:
We don't want to inflate delete Transactions, but we do still want
to pass the delta itself along.

Test Plan: tested locally

Reviewers: evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3647
2017-01-12 10:21:45 -08:00
Christine Spang ed57422412 [local-sync] Enable toggling ENABLE_SEQUELIZE_DEBUG_LOGGING on launch via an env var
It's much more convenient to be able to turn this on/off without
editing the code.
2017-01-12 07:43:34 -08:00
Christine Spang d36ae8db3c [local-sync] Still download messages when they have no body
There are plenty of valid use cases for sending subject-only emails,
and we also want to still download the headers and create message
objects if e.g. the email consists of only an event invitation or
an attachment.
2017-01-11 18:08:20 -08:00
Juan Tejada 3eb450e22c [local-sync] Make sure IMAPConnection times out correctly
Summary:
This commit passes down the `socketTimeout` option to node-imap. However, just
passing this option doesn't seem to work reliably, so this commit manually implements
the socketTimeout option for our IMAPConnection.

How it works is that basically every operation is wrapped with a timeout by
augmenting  the `createConnectionPromise` construct that already existed.

Test Plan:
Locally, tested by sleeping computer and turning off wifi. The
connection will successfully error and be restarted. It will reconnect when the
network is available again

Reviewers: khamidou, halla, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3642
2017-01-11 16:48:10 -08:00
Christine Spang e1271cf25c [local-sync] Give Nylas Mail messages a different Message-ID from API messages
Summary:
We may find it useful at some point to be able to tell which messages in
a user's mailbox were sent using N1/the REST API vs Nylas Mail.

Test Plan: manual

Reviewers: evan, juan

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D3631
2017-01-11 15:51:12 -08:00
Karim Hamidou 9136b0592b [fix] Add a poor man's two-phase commit algorithm for syncback tasks.
Summary:
Sometimes things go very wrong when trying to syncback an action. For example, the worker window could crash, preventing us from marking the current task as failed. What's worse, another sync iteration could try to run the task which crashed, thinking it a new one. To prevent this, this diff adds a fourth syncback task state, `INPROGRESS`.

New syncback tasks are marked as `INPROGRESS` before being executed. When they complete we mark them as `SUCCEEDED/FAILED`. Stray `INPROGRESS` tasks are automatically marked as `FAILED` at the beginning of every sync iteration, to make sure we don't retry them again.

Test Plan: Tested manually.

Reviewers: evan, juan

Reviewed By: evan, juan

Differential Revision: https://phab.nylas.com/D3635
2017-01-11 12:04:58 -08:00
Evan Morikawa 47f5880d18 [local-sync] fix multiple sync loops starting
A bug allowed multiple sync loop processes to start. This could lead to
double sending and the sync loop appearing as thouogh it couldn't be
interrupted
2017-01-10 18:24:38 -08:00
Michael Pfister a738d8a622 Add ability to debug with chrome dev tools in cloud-api 2017-01-10 17:31:51 -08:00
Juan Tejada 202d56d3f2 Fix error reporter causing crash due to infinite recursion 2017-01-10 15:30:30 -08:00
Christine Spang 9eb1aef139 [local-sync] Properly handle multiple occurrences of From/To/Cc/Bcc headers
Summary:
Well-behaved MUAs don't do this, but it is totally legal and we should
handle it.

The Python sync engine handles this properly also:
7db949fec9/sync-engine/inbox/util/addr.py (L26-L47)

(Found this out while scratching my head over the output format of
mimelib.parseHeaders---turns out it's an array for a reason:

> let to = mimelib.parseHeaders(`To: Christine Spang <spang@nylas.com>
... To: Foo Bar <foo@example.com>`);
undefined
> to
{ to:
   [ 'Christine Spang <spang@nylas.com>',
     'Foo Bar <foo@example.com>' ] }

)

Test Plan: unit test included

Reviewers: halla, jackie, mark

Reviewed By: mark

Differential Revision: https://phab.nylas.com/D3625
2017-01-10 15:07:36 -08:00
Christine Spang 15ac9f795b [local-sync] Remove deprecated comment
With the latest update to N1's CSS, this is no longer true---though a theme
can easily override the font to monospace if so desired.
2017-01-10 13:39:54 -08:00
Juan Tejada 79006f692d [local-sync] Fix check for new mail updates on inbox folder 2017-01-10 12:19:15 -08:00
Juan Tejada b74aad7314 [local-sync] Run send tasks before other syncback tasks
Summary: Update `_getNewSyncbackTasks` to return any send tasks first, and then others

Test Plan: locally

Reviewers: halla, evan

Reviewed By: halla, evan

Differential Revision: https://phab.nylas.com/D3627
2017-01-10 12:11:34 -08:00
Christine Spang 27b2c41fcc [local-sync] Make comment about Date/INTERNALDATE & message hashes better 2017-01-10 12:05:14 -08:00
Juan Tejada 80708dacbc [local-sync] Make syncback task execution interruptible
Summary:
See title. Got rid of that syncback-worker class which was kind of useless and
made things harder. My b.

Test Plan: locally

Reviewers: evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3624
2017-01-10 10:45:53 -08:00
Christine Spang a234570118 [local-sync] Rename extract{Snippet,Contacts} in message-factory
Summary:
We have another function called extractContacts, in its own file,
extract-contacts.js, which is used to create Contact objects. This has
confused me a number of times and also leads to grep collisions.

This patch also makes the snippet unit tests pass again after a recent
API change.

Test Plan: included unit tests, manual

Reviewers: halla, evan, juan

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D3623
2017-01-10 10:41:35 -08:00
Christine Spang fb705fc5dd [local-sync] Remove unused message update hook
Summary:
Message bodies, drafts aside, are immutable, and we set the snippet on
new messages manually in parseFromImap()---meaning this hook, if
invoked, is likely to replace the snippet with a broken version computed
with this old implementation. If we need a hook in the future (e.g. for
updating drafts), it should use the snippet function from
message-factory.

Test Plan: n/a

Reviewers: juan, halla

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D3622
2017-01-10 10:39:43 -08:00
Halla Moore 1e6f7a6e6f [local-sync] Don't delete messages via cascade when a folder is deleted
1. It could be expensive to delete many messages at the exact moment
   when the folder is deleted
2. The folder delete could actually just be a rename, and if we
   deleted all the messages, we would have to re-process them all
3. We already do a clean-up check for orphaned messages at the end
   of the sync loop, where we already know if the folder was
   actually deleted or just renamed
2017-01-10 10:37:08 -08:00
Evan Morikawa b03c0c9bc2 [isomorphic-core] don't try and inflate delete deltas
Summary:
If we inflate delete deltas, the object we're trying to find won't exist
anymore (we just deleted it!). This is likely causing the `While inflating
${sourceName} transactions, we couldn't find models for some ${modelName}
IDs` error.

Fixes T7436

Test Plan: manual

Reviewers: spang, juan, halla

Reviewed By: halla

Maniphest Tasks: T7436

Differential Revision: https://phab.nylas.com/D3621
2017-01-10 10:21:14 -08:00
Christine Spang ac08163c51 [local-sync] s/queryes/queries/ 2017-01-10 08:26:44 -08:00
Christine Spang b618c4ef28 [local-sync] Fix typo in ENABLE_SEQUELIZE_DEBUG_LOGGING 2017-01-10 08:16:16 -08:00
Halla Moore 2ed1a03d34 [local-sync, iso-core]: Cascade deletes on hasMany associations
Summary:
Delete associated children when a parent is deleted to prevent foreign
key constraint errors. Also make sure any child hooks are run.

Test Plan: tested locally

Reviewers: evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3620
2017-01-09 18:13:09 -08:00
Halla Moore aaf0b04ae3 [local-sync] Add a hasAttachment attribute to threads
Summary: N1 uses this to show the little attachment icon in the thread list.

Test Plan: tested locally

Reviewers: evan, juan, spang

Reviewed By: spang

Differential Revision: https://phab.nylas.com/D3617
2017-01-09 17:20:55 -08:00
Christine Spang a959d546d6 [local-sync] Update comment 2017-01-09 15:24:55 -08:00
Juan Tejada 82dbc222b5 [local-sync] Fix send, correctly check for presence of headers 2017-01-09 15:17:19 -08:00
Juan Tejada d48ed92d66 [local-sync] Make the sync loop interruptible
Summary:
This commit introduces interruptible sync operations. Now, the `SyncWorker`, `FetchFolderList` operation and `FetchMessagesInFolder` operation can be interrupted at several points during their execution. This improves the performance of SyncbackTasks, which now run almost immediately.

To achieve this, this commit adds an Interruptible abstraction, which is an object that can run functions and interrupt them at points marked by the function. For more info on how this works, see the docs on the Interruptible class.

This commit also splits up the SyncWorker a little bit to make it smaller, byadding a SyncbackTaskWorker.

Depends on D3613

Test Plan: Manual

Reviewers: spang, mark, jackie, khamidou, evan, halla

Reviewed By: evan, halla

Differential Revision: https://phab.nylas.com/D3612
2017-01-09 14:43:15 -08:00
Evan Morikawa 73db7a4e46 [local-sync] fix changedsince highestmodseq causing N1 crash
Since we weren't giving Node IMAP the proper format for the changedsince
flag, and since node IMAP never warned of improper schemas, we weren't
properly requesting the correct range. This would cause us to request the
metadata attributes of EVERY message in the mailbox and attempt to store
them in a hash. This would eventually lead to a memory leak and take down
the worker window, which caused other subtle issues like sends failing
when the worker window dropped task half way through their perform remotes
and never re-sent the deltas notifying of their success or failure.

This was only triggered when new highestmodseq numbers fired on the remote
server, which would be triggered by the underlying mailbox getting folders
or labels changed on messages
2017-01-09 14:07:31 -08:00
Christine Spang 7073e19fe7 [local-sync] Don't filter contacts w/out emails out of To/From/Cc/Bcc fields
We separately filter out contacts without email addresses before
committing to the contacts table in the database for autocomplete (in
isContactMeaningful()), and if we filter out these already we can end up
excluding legitimate elements of the headers. For example, the Clutter
feature of Office 365 sends emails with a From: header like this:

From: Microsoft Outlook

Fixes: T7413
2017-01-09 13:45:18 -08:00
Halla Moore 1ba4a6eaf2 [local-sync] Add support for inline-images
Summary:
Extract files for inline attachments and store their content id

Fixes T7414

Test Plan: tested locally

Reviewers: evan, spang

Reviewed By: spang

Maniphest Tasks: T7414

Differential Revision: https://phab.nylas.com/D3609
2017-01-09 10:44:42 -08:00
Tomasz Finc 2c0fd79707 Fixing most lint errors in error-logger
Summary: Cleaning up almost all the linting errors in the logger

Test Plan: ... run the build

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3605
2017-01-09 10:38:48 -08:00
Evan Morikawa afdc5a3ef9 [local-api] linter fixes 2017-01-09 09:57:06 -08:00
Evan Morikawa 4a760ff5ec [local-sync] audit database indices
Summary:
Fixes T7398

We were create unnecessary and duplicate indices for the IDs of all of
our objects and increasing db write overhead.

We were not creating the correct reverse index for our join tables.

The search API'd db is already in scope of the accountId, this is an
unnecessary constraint on the query

Test Plan: manual

Reviewers: spang, juan

Reviewed By: juan

Maniphest Tasks: T7398

Differential Revision: https://phab.nylas.com/D3606
2017-01-09 09:45:33 -08:00
Christine Spang 6d72bb2aaf [local-sync] Optimize header & MIME structure download
Summary:
Headers can be quite big, so we might as well download and store only
the ones that we care about. This patch also makes it so we stop
downloading MIME structures twice per message.

While it's possible that we _may_ want to make more headers accessible
later, we don't currently make the generic pile of headers accessible to
N1 or N1 plugins in any way, so doing that would end up requiring
changes to the sync code regardless. I think it's worth optimizing the
base experience rather than trying to predict what we may want in the
future. Plus, it seems more likely that we'll want to build future
extensibility using thread metadata, rather than message headers.

On inboxapptest1@fastmail.fm, this patch decreases the size of the
generated sqlite file for a fully synced mailbox by 35%.

Test Plan: manual

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3611
2017-01-08 13:27:10 -08:00
Christine Spang 9d05bb9d1c [local-sync] don't play fast and loose with newlines, or a lack thereof 2017-01-07 14:34:03 -08:00
Christine Spang 8238fe9594 [local-sync] Correctly handle messages with non-alternative multipart text bodies
Summary:
It's possible to have multiple inline HTML parts in a message, or even
a multipart/alternative part that contains text and HTML, followed by a
plaintext signature. Previously, if there was more than one text part in
an email, we would pick the _last_ text/html or text/plain part that we
found, and treat that as the entire message body. This works most of the
time, but fails to display the full message body in some edge cases.
This patch fixes that by resolving multipart/alternative subparts to a
single part in the mimepart fetch stage, and then treating each desired
mime part separately when parsing the message, concatenating them if
there are multiple.

This makes K2's handling of multipart MIME message text better,
bug-wise, than the Python sync engine's, which has been mangling some
rare messages forever. (Example from my email: every email from the MIT
EECS Jobs List has never displayed the mailing list signature in N1.)

Note that this patch also removes our tentative support for PGP
encrypted messages. I'd rather add that back in later when I've dug up
some real example messages to test on, rather than leaving it in in its
current not-really-tested and probably not-really-working state, since
it makes it harder to make sure that the rest of the logic isn't broken.

Test Plan: manual for now - added examples of this to my growing list of regression tests to add to the message parser unit tests once I fix them

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3600
2017-01-07 14:11:27 -08:00
Christine Spang 78aa3291d6 [local-sync] Bump limit on finding matching threads
I'm kind of worried that weird stuff may happen on short, common
thread subjects. The Python sync engine has _no_ limit, and it seems
to work OK.
2017-01-07 13:13:22 -08:00
Christine Spang 4aa6cb3ca1 [local-sync] Port generic IMAP threading logic from Python Sync Engine
Summary:
We sync messages in the same order as the Python sync engine (newest to
oldest, generally), so we should be able to just use the same threading
algorithm. While we may still want to take into account References /
In-Reply-To at some point, this is a big step up from the current
thread-matching-only.

Test Plan: manual --- could pretty easily port the unit tests from the python codebase if we wanted

Reviewers: khamidou, juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3604
2017-01-07 13:11:33 -08:00
Halla Moore c4588ec011 [local-sync] Re-add code to associate labels with new messages
This code was accidentally removed during a merge conflict. Code was
originally added in commit 333647.
2017-01-07 12:48:37 -08:00