« get me outta code hell

data: withReverseContributionList: cache all results per data array - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2024-01-17 14:15:24 -0400
committer(quasar) nebula <qznebula@protonmail.com>2024-01-17 16:09:59 -0400
commitebe2a4d41c55be1250d4964ab16b788f70d5943b (patch)
tree6dbf9ee10b0a0ff955c7f3d9be9c608c9a3bc394
parent61e675cd51946c5cc2bbdd500df620e0c870bd3d (diff)
data: withReverseContributionList: cache all results per data array
-rw-r--r--src/data/composite/wiki-data/withReverseContributionList.js42
1 files changed, 38 insertions, 4 deletions
diff --git a/src/data/composite/wiki-data/withReverseContributionList.js b/src/data/composite/wiki-data/withReverseContributionList.js
index 71e3c1a..7b07e24 100644
--- a/src/data/composite/wiki-data/withReverseContributionList.js
+++ b/src/data/composite/wiki-data/withReverseContributionList.js
@@ -4,6 +4,10 @@
 // up subsequent similar accesses. Reverse contribution lists are the most
 // costly in live-dev-server, but we intend to expand the impelemntation here
 // to reverse reference lists in general later on.
+//
+// This has absolutely not been rigorously tested with altering properties of
+// data objects in a wiki data array which is reused. If a new wiki data array
+// is used, a fresh cache will always be created.
 
 import {input, templateCompositeFrom} from '#composite';
 
@@ -11,6 +15,12 @@ import {exitWithoutDependency} from '#composite/control-flow';
 
 import inputWikiData from './inputWikiData.js';
 
+// Mapping of reference list property to WeakMap.
+// Each WeakMap maps a wiki data array to another weak map,
+// which in turn maps each referenced thing to an array of
+// things referencing it.
+const caches = new Map();
+
 export default templateCompositeFrom({
   annotation: `withReverseContributionList`,
 
@@ -35,11 +45,35 @@ export default templateCompositeFrom({
         [input.myself()]: myself,
         [input('data')]: data,
         [input('list')]: list,
-      }) =>
-        continuation({
+      }) => {
+        if (!caches.has(list)) {
+          caches.set(list, new WeakMap());
+        }
+
+        const cache = caches.get(list);
+
+        if (!cache.has(data)) {
+          const cacheRecord = new WeakMap();
+
+          for (const referencingThing of data) {
+            const referenceList = referencingThing[list];
+            for (const {who: referencedThing} of referenceList) {
+              if (cacheRecord.has(referencedThing)) {
+                cacheRecord.get(referencedThing).push(referencingThing);
+              } else {
+                cacheRecord.set(referencedThing, [referencingThing]);
+              }
+            }
+          }
+
+          cache.set(data, cacheRecord);
+        }
+
+        return continuation({
           ['#reverseContributionList']:
-            data.filter(thing => thing[list].some(({who}) => who === myself)),
-        }),
+            cache.get(data).get(myself) ?? [],
+        });
+      },
     },
   ],
 });