Refactor IMAP sync.

Summary:
This commit restructures the IMAP sync engine logic to use a more
object-oriented design, favoring implementation inheritance over explicit
state-and-implementation passing.

The primary motivation for this is that I was finding it really challenging to
do surgery on the mailsync code, for two reasons. First, passing functions
around made it very difficult to see where any given function is being invoked,
because you have to know that create_gmail_message(...) may actually be called
as msg_create_fn(...), etc. Second, it's really hard to modify the state
that's being passed around, because you have to change like seven levels of
function parameters. This pattern was leading us to repeatedly query for things
we already in principle know, like accessing the active Namespace instance, or
doing weird stuff like reading the account_id from the crispin_client.
This carries a significant performance cost when aggregated over the lifetime
of a sync.

So this commit is essentially preparation for making targeted changes
to address both performance and correctness. Concretely, it does the following:
* Implement most logic in methods of the FolderSyncEngine class, which runs the
  sync state machine. Implement derived classes CondstoreFolderSyncEngine and
  GmailFolderSyncEngine, which override specific functionality for condstore
  sync and Gmail sync.

* Move the SyncMonitor logic (the thing that gets instantiated from the
  SyncService and starts the individual folder syncs) into its own module
  backends.imap.monitor. The SyncService actually instantiates lightweight
  derived classes GmailSyncMonitor, GenericSyncMonitor, etc. depending on
  provider, but the only difference among them is which type of
  FolderSyncEngine gets instantiated.

Smaller associated changes:
* Rename backends.imap.account to backends.imap.common, to prevent confusion
  over whether 'account' is an Account instance or a module.
* Use structlog's greenlet-local context facility to bind context to the logger
  on a per-greenlet basis. This means that we can just do log = get_logger() in
  in a greenlet and have it come with the right bound attributes, instead of
  needing to pass around a log object.
* Define 'mailsync_session_scope' as an alias for
  'session_scope(ignore_soft_deletes=False)'
* Remove some unused code.
* Clean up some parameter mismatches in condstore code.

This is obviously a pretty gnarly patch, but I think if we eat our wheaties now
it will pay off later.

Test Plan:
Working on it. Probably going to do a 'sync-diff' for various
providers, by running a sync with and without this change, and checking that
the results are the same.

Reviewers: spang, khamidou

Subscribers: kav-ya, charles

Differential Revision: https://review.inboxapp.com/D378
[SCHEMA] Simplify transaction log construction.

This commit implements a leaner, meaner transaction log. Instead of storing an
ORM-derived delta, only store a snapshot of the API representation of the
versioned object. This reduces the volume of data we store, makes constructing
the transaction faster, and removes some complexity left over from when we were
trying to infer syncback actions from the transaction log. It's less generic,
but better suited to our actual application.

Includes some simplifications to the Lens model -- just removing parts that
would be broken by this change, and were part of webhooks but are unlikely to
be repurposed into ping.
Use an S3 connection pool for blob saving.

It turns out that initializing a new S3 connection for every object you save to
S3 is really expensive. Instead, maintain a pool of worker greenlets, each of
which maintains a persistent S3 connection. (Note that an S3 connection cannot
be shared across greenlets.)