Repository: dbt-labs/dbt-core

Issue:
[PP] KeyError if model + its yaml properties deleted simultaneously
### Describe the bug

While partial parsing is enabled, if a model and its yaml properties are deleted at the same time, it results in a key error.

### Steps To Reproduce

1. Start with:
```sql
-- models/my_model.sql
select 1 as fun
```
```yml
# models/schema.yml
version: 2
models:
  - name: my_model
    columns:
      - name: id
        tests:
          - unique
```
2. Parse the project:
```
$ dbt --no-partial-parse parse
Running with dbt=0.20.0-rc1
19:28:40 | Start parsing.
19:28:40 | Dependencies loaded
19:28:40 | ManifestLoader created
19:28:41 | Manifest loaded
19:28:41 | Manifest checked
19:28:41 | Flat graph built
19:28:41 | Manifest loaded
19:28:41 | Performance info: target/perf_info.json
19:28:41 | Done.
```
3. Delete both files. Re-parse the project:
```
$ dbt --partial-parse parse
Running with dbt=0.20.0-rc1
19:28:53 | Start parsing.
19:28:53 | Dependencies loaded
19:28:53 | ManifestLoader created
Partial parsing enabled: 2 files deleted, 0 files added, 0 files changed.
Encountered an error:
'model.my_project.my_model'
```

### Expected behavior
dbt should partially re-parse the project without any problems. Partial re-parses _are_ successful if only one file is deleted at a time, and it doesn't matter the order.

### Screenshots and log output
```
  File "/Users/jerco/dev/product/dbt/core/dbt/parser/partial.py", line 129, in get_parsing_files
    self.delete_from_saved(file_id)
  File "/Users/jerco/dev/product/dbt/core/dbt/parser/partial.py", line 180, in delete_from_saved
    self.remove_mssat_file(saved_source_file)
  File "/Users/jerco/dev/product/dbt/core/dbt/parser/partial.py", line 267, in remove_mssat_file
    self.remove_node_in_saved(source_file, unique_id)
  File "/Users/jerco/dev/product/dbt/core/dbt/parser/partial.py", line 226, in remove_node_in_saved
    node = self.saved_manifest.nodes.pop(unique_id)
```

### System information
**Which database are you using dbt with?**
- [x] postgres

**The output of `dbt --version`:**
This error crops up in both:
- `0.20.0rc1` (as released on June 4)
- built from `develop` / `0.20.latest`



Discussion:

Resolving patch:
diff --git a/core/dbt/parser/partial.py b/core/dbt/parser/partial.py
--- a/core/dbt/parser/partial.py
+++ b/core/dbt/parser/partial.py
@@ -222,6 +222,10 @@ def update_mssat_in_saved(self, new_source_file, old_source_file):
         self.remove_node_in_saved(new_source_file, unique_id)
 
     def remove_node_in_saved(self, source_file, unique_id):
+        # Has already been deleted by another action
+        if unique_id not in self.saved_manifest.nodes:
+            return
+
         # delete node in saved
         node = self.saved_manifest.nodes.pop(unique_id)
         self.deleted_manifest.nodes[unique_id] = node


Test patch:
diff --git a/test/integration/068_partial_parsing_tests/test_partial_parsing.py b/test/integration/068_partial_parsing_tests/test_partial_parsing.py
--- a/test/integration/068_partial_parsing_tests/test_partial_parsing.py
+++ b/test/integration/068_partial_parsing_tests/test_partial_parsing.py
@@ -90,12 +90,14 @@ def test_postgres_pp_models(self):
         self.assertNotIn(unique_test_id, manifest.nodes.keys())
         self.assertEqual(len(results), 1)
 
-        # go back to previous version of schema file, removing patch and test for model three
+        # go back to previous version of schema file, removing patch, test, and model for model three
         shutil.copyfile('extra-files/models-schema1.yml', 'models-a/schema.yml')
+        os.remove(normalize('models-a/model_three.sql'))
         results = self.run_dbt(["--partial-parse", "run"])
-        self.assertEqual(len(results), 3)
+        self.assertEqual(len(results), 2)
 
         # remove schema file, still have 3 models
+        shutil.copyfile('extra-files/model_three.sql', 'models-a/model_three.sql')
         os.remove(normalize('models-a/schema.yml'))
         results = self.run_dbt(["--partial-parse", "run"])
         self.assertEqual(len(results), 3)