Repository: vertexproject/synapse

Issue:
Synapse fails to create syn:tag node when applying a previously created but deleted tag
New tags can be applied to nodes without first creating an associated syn:tag node; expected behavior is that the first time you apply a new tag, Synapse automatically creates the syn:tag node in the background.
This is true for never-before-seen tags. However, if a tag and its associated syn:tag node are created, then deleted, and they you try to create / apply that same tag again, Synapse fails to create the syn:tag node.
Example (where syn:tag=hurr.derp was previously created, applied to a test node, removed from the test node, and the syn:tag node deleted):
```
cli> ask inet:fqdn=woot.com [#hurr.derp]
inet:fqdn = woot.com
    #foo.bar (added 2017/06/20 19:59:02.854)
    #hurr.derp (added 2017/08/02 21:07:18.579)
(1 results)

cli> ask syn:tag=hurr.derp
(0 results)
```

Discussion:

Patch:
diff --git a/synapse/cores/common.py b/synapse/cores/common.py
index 070cd0c4e..3364680f6 100644
--- a/synapse/cores/common.py
+++ b/synapse/cores/common.py
@@ -919,6 +919,10 @@ class Cortex(EventBus, DataModel, Runtime, Configable, s_ingest.IngestApi):
         # do the (possibly very heavy) removal of the tag from all known forms.
         [self.delTufoTag(t, valu) for t in self.getTufosByTag(valu)]
 
+        # Flush the tag caches
+        self._core_tags.clear()
+        self._core_tagforms.clear()
+
     @on('node:form', form='syn:tag')
     def _onFormSynTag(self, mesg):
         valu = mesg[1].get('valu')


Test patch:
diff --git a/synapse/tests/test_cortex.py b/synapse/tests/test_cortex.py
index 4255a95f0..b7fcb9880 100644
--- a/synapse/tests/test_cortex.py
+++ b/synapse/tests/test_cortex.py
@@ -1012,6 +1012,28 @@ class CortexTest(SynTest):
         self.eq(len(core.getTufosByTag('lulz.rofl', form='foo')), 0)
         self.eq(len(core.getTufosByTag('lulz.rofl.zebr', form='foo')), 0)
 
+        # Now we need to retag a node, ensure that the tag is on the node and the syn:tag nodes exist again
+        wait = core.waiter(1, 'node:tag:add')
+        node = core.addTufoTag(hehe, 'lulz.rofl.zebr')
+        wait.wait(timeout=2)
+
+        self.isin('#lulz.rofl.zebr', node[1])
+        self.nn(core.getTufoByProp('syn:tag', 'lulz'))
+        self.nn(core.getTufoByProp('syn:tag', 'lulz.rofl'))
+        self.nn(core.getTufoByProp('syn:tag', 'lulz.rofl.zebr'))
+
+        # Recreate expected results from #320 to ensure
+        # we're also doing the same via storm
+        self.eq(len(core.eval('[inet:fqdn=w00t.com +#some.tag]')), 1)
+        self.eq(len(core.eval('inet:fqdn=w00t.com totags(leaf=0)')), 2)
+        self.eq(len(core.eval('syn:tag=some')), 1)
+        self.eq(len(core.eval('syn:tag=some.tag')), 1)
+        self.eq(len(core.eval('syn:tag=some delnode(force=1)')), 0)
+        self.eq(len(core.eval('inet:fqdn=w00t.com totags(leaf=0)')), 0)
+        self.eq(len(core.eval('inet:fqdn=w00t.com [ +#some.tag ]')), 1)
+        self.eq(len(core.eval('inet:fqdn=w00t.com totags(leaf=0)')), 2)
+        self.eq(len(core.eval('syn:tag=some')), 1)
+        self.eq(len(core.eval('syn:tag=some.tag')), 1)
         core.fini()
 
     def test_cortex_splices(self):