We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
NPM sync is broken
https://gratipay.slack.com/archives/C36LJJF9V/p1494580201702422

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gratipay/sync_npm.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 from __future__ import absolute_import, division, print_function, unicode_literals
3 
4 import requests
5 from couchdb import Database
6 
7 from gratipay.models.package import NPM, Package
8 
9 
10 REGISTRY_URL = 'https://replicate.npmjs.com/'
11 
12 
13 def get_last_seq(db):
14     return db.one('SELECT npm_last_seq FROM worker_coordination')
15 
16 
17 def production_change_stream(seq):
18     """Given a sequence number in the npm registry change stream, start
19     streaming from there!
20     """
21     return Database(REGISTRY_URL).changes(feed='continuous', include_docs=True, since=seq)
22 
23 
24 def process_doc(doc):
25     """Return a smoothed-out doc, or None if it's not a package doc, meaning
26     there's no name key and it's probably a design doc, per:
27 
28         https://github.com/npm/registry/blob/aef8a275/docs/follower.md#clean-up
29 
30     """
31     if 'name' not in doc:
32         return None
33     name = doc['name']
34     description = doc.get('description', '')
35     emails = [e for e in [m.get('email') for m in doc.get('maintainers', [])] if e.strip()]
36     return {'name': name, 'description': description, 'emails': sorted(set(emails))}
37 
38 
39 def consume_change_stream(stream, db):
40     """Given an iterable of CouchDB change notifications and a
41     :py:class:`~GratipayDB`, read from the stream and write to the db.
42 
43     The npm registry is a CouchDB app, which means we get a change stream from
44     it that allows us to follow registry updates in near-realtime. Our strategy
45     here is to maintain open connections to both the registry and our own
46     database, and write as we read.
47 
48     """
49     with db.get_connection() as connection:
50         for change in stream:
51 
52             # Decide what to do.
53             if change.get('deleted'):
54                 package = Package.from_names(NPM, change['id'])
55                 assert package is not None  # right?
56                 op, kw = package.delete, {}
57             else:
58                 op = Package.upsert
59                 kw = process_doc(change['doc'])
60                 if not kw:
61                     continue
62                 kw['package_manager'] = NPM
63 
64             # Do it.
65             cursor = connection.cursor()
66             kw['cursor'] = cursor
67             op(**kw)
68             cursor.run('UPDATE worker_coordination SET npm_last_seq=%(seq)s', change)
69             connection.commit()
70 
71 
72 def check(db, _print=print):
73     ours = db.one('SELECT npm_last_seq FROM worker_coordination')
74     theirs = int(requests.get(REGISTRY_URL).json()['update_seq'])
75     _print("count#npm-sync-lag={}".format(theirs - ours))
76
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gratipay/sync_npm.py b/gratipay/sync_npm.py
--- a/gratipay/sync_npm.py
+++ b/gratipay/sync_npm.py
@@ -52,7 +52,11 @@
             # Decide what to do.
             if change.get('deleted'):
                 package = Package.from_names(NPM, change['id'])
-                assert package is not None  # right?
+                if not package:
+                    # As a result of CouchDB's compaction algorithm, we might
+                    # receive 'deleted' events for docs even if we haven't seen
+                    # the corresponding events for when the doc was created
+                    continue
                 op, kw = package.delete, {}
             else:
                 op = Package.upsert

{"golden_diff": "diff --git a/gratipay/sync_npm.py b/gratipay/sync_npm.py\n--- a/gratipay/sync_npm.py\n+++ b/gratipay/sync_npm.py\n@@ -52,7 +52,11 @@\n             # Decide what to do.\n             if change.get('deleted'):\n                 package = Package.from_names(NPM, change['id'])\n-                assert package is not None  # right?\n+                if not package:\n+                    # As a result of CouchDB's compaction algorithm, we might\n+                    # receive 'deleted' events for docs even if we haven't seen\n+                    # the corresponding events for when the doc was created\n+                    continue\n                 op, kw = package.delete, {}\n             else:\n                 op = Package.upsert\n", "issue": "NPM sync is broken\nhttps://gratipay.slack.com/archives/C36LJJF9V/p1494580201702422\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport requests\nfrom couchdb import Database\n\nfrom gratipay.models.package import NPM, Package\n\n\nREGISTRY_URL = 'https://replicate.npmjs.com/'\n\n\ndef get_last_seq(db):\n    return db.one('SELECT npm_last_seq FROM worker_coordination')\n\n\ndef production_change_stream(seq):\n    \"\"\"Given a sequence number in the npm registry change stream, start\n    streaming from there!\n    \"\"\"\n    return Database(REGISTRY_URL).changes(feed='continuous', include_docs=True, since=seq)\n\n\ndef process_doc(doc):\n    \"\"\"Return a smoothed-out doc, or None if it's not a package doc, meaning\n    there's no name key and it's probably a design doc, per:\n\n        https://github.com/npm/registry/blob/aef8a275/docs/follower.md#clean-up\n\n    \"\"\"\n    if 'name' not in doc:\n        return None\n    name = doc['name']\n    description = doc.get('description', '')\n    emails = [e for e in [m.get('email') for m in doc.get('maintainers', [])] if e.strip()]\n    return {'name': name, 'description': description, 'emails': sorted(set(emails))}\n\n\ndef consume_change_stream(stream, db):\n    \"\"\"Given an iterable of CouchDB change notifications and a\n    :py:class:`~GratipayDB`, read from the stream and write to the db.\n\n    The npm registry is a CouchDB app, which means we get a change stream from\n    it that allows us to follow registry updates in near-realtime. Our strategy\n    here is to maintain open connections to both the registry and our own\n    database, and write as we read.\n\n    \"\"\"\n    with db.get_connection() as connection:\n        for change in stream:\n\n            # Decide what to do.\n            if change.get('deleted'):\n                package = Package.from_names(NPM, change['id'])\n                assert package is not None  # right?\n                op, kw = package.delete, {}\n            else:\n                op = Package.upsert\n                kw = process_doc(change['doc'])\n                if not kw:\n                    continue\n                kw['package_manager'] = NPM\n\n            # Do it.\n            cursor = connection.cursor()\n            kw['cursor'] = cursor\n            op(**kw)\n            cursor.run('UPDATE worker_coordination SET npm_last_seq=%(seq)s', change)\n            connection.commit()\n\n\ndef check(db, _print=print):\n    ours = db.one('SELECT npm_last_seq FROM worker_coordination')\n    theirs = int(requests.get(REGISTRY_URL).json()['update_seq'])\n    _print(\"count#npm-sync-lag={}\".format(theirs - ours))\n", "path": "gratipay/sync_npm.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport requests\nfrom couchdb import Database\n\nfrom gratipay.models.package import NPM, Package\n\n\nREGISTRY_URL = 'https://replicate.npmjs.com/'\n\n\ndef get_last_seq(db):\n    return db.one('SELECT npm_last_seq FROM worker_coordination')\n\n\ndef production_change_stream(seq):\n    \"\"\"Given a sequence number in the npm registry change stream, start\n    streaming from there!\n    \"\"\"\n    return Database(REGISTRY_URL).changes(feed='continuous', include_docs=True, since=seq)\n\n\ndef process_doc(doc):\n    \"\"\"Return a smoothed-out doc, or None if it's not a package doc, meaning\n    there's no name key and it's probably a design doc, per:\n\n        https://github.com/npm/registry/blob/aef8a275/docs/follower.md#clean-up\n\n    \"\"\"\n    if 'name' not in doc:\n        return None\n    name = doc['name']\n    description = doc.get('description', '')\n    emails = [e for e in [m.get('email') for m in doc.get('maintainers', [])] if e.strip()]\n    return {'name': name, 'description': description, 'emails': sorted(set(emails))}\n\n\ndef consume_change_stream(stream, db):\n    \"\"\"Given an iterable of CouchDB change notifications and a\n    :py:class:`~GratipayDB`, read from the stream and write to the db.\n\n    The npm registry is a CouchDB app, which means we get a change stream from\n    it that allows us to follow registry updates in near-realtime. Our strategy\n    here is to maintain open connections to both the registry and our own\n    database, and write as we read.\n\n    \"\"\"\n    with db.get_connection() as connection:\n        for change in stream:\n\n            # Decide what to do.\n            if change.get('deleted'):\n                package = Package.from_names(NPM, change['id'])\n                if not package:\n                    # As a result of CouchDB's compaction algorithm, we might\n                    # receive 'deleted' events for docs even if we haven't seen\n                    # the corresponding events for when the doc was created\n                    continue\n                op, kw = package.delete, {}\n            else:\n                op = Package.upsert\n                kw = process_doc(change['doc'])\n                if not kw:\n                    continue\n                kw['package_manager'] = NPM\n\n            # Do it.\n            cursor = connection.cursor()\n            kw['cursor'] = cursor\n            op(**kw)\n            cursor.run('UPDATE worker_coordination SET npm_last_seq=%(seq)s', change)\n            connection.commit()\n\n\ndef check(db, _print=print):\n    ours = db.one('SELECT npm_last_seq FROM worker_coordination')\n    theirs = int(requests.get(REGISTRY_URL).json()['update_seq'])\n    _print(\"count#npm-sync-lag={}\".format(theirs - ours))\n", "path": "gratipay/sync_npm.py"}]}