« get me outta code hell

data: withReverseReferenceList: mirror withReverseContributionList - 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:18:20 -0400
committer(quasar) nebula <qznebula@protonmail.com>2024-01-17 16:10:10 -0400
commitc712bb783a2c213d036255f6468b0c06df8efc79 (patch)
tree9fd930423a978495e567aa1028612d893229a594
parentebe2a4d41c55be1250d4964ab16b788f70d5943b (diff)
data: withReverseReferenceList: mirror withReverseContributionList
-rw-r--r--src/data/composite/wiki-data/withReverseContributionList.js12
-rw-r--r--src/data/composite/wiki-data/withReverseReferenceList.js52
2 files changed, 54 insertions, 10 deletions
diff --git a/src/data/composite/wiki-data/withReverseContributionList.js b/src/data/composite/wiki-data/withReverseContributionList.js
index 7b07e24a..eccb58b7 100644
--- a/src/data/composite/wiki-data/withReverseContributionList.js
+++ b/src/data/composite/wiki-data/withReverseContributionList.js
@@ -1,9 +1,9 @@
-// Analogous implementation for withReverseReferenceList, but contributions.
+// Analogous implementation for withReverseReferenceList, for contributions.
+// This is all duplicate code and both should be ported to the same underlying
+// data form later on.
 //
 // This implementation uses a global cache (via WeakMap) to attempt to speed
-// 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.
+// up subsequent similar accesses.
 //
 // 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
@@ -57,6 +57,10 @@ export default templateCompositeFrom({
 
           for (const referencingThing of data) {
             const referenceList = referencingThing[list];
+
+            // Destructuring {who} is the only unique part of the
+            // withReverseContributionList implementation, compared to
+            // withReverseReferneceList.
             for (const {who: referencedThing} of referenceList) {
               if (cacheRecord.has(referencedThing)) {
                 cacheRecord.get(referencedThing).push(referencingThing);
diff --git a/src/data/composite/wiki-data/withReverseReferenceList.js b/src/data/composite/wiki-data/withReverseReferenceList.js
index a025b5ed..2d7a421b 100644
--- a/src/data/composite/wiki-data/withReverseReferenceList.js
+++ b/src/data/composite/wiki-data/withReverseReferenceList.js
@@ -1,5 +1,15 @@
 // Check out the info on reverseReferenceList!
 // This is its composable form.
+//
+// This implementation uses a global cache (via WeakMap) to attempt to speed
+// up subsequent similar accesses.
+//
+// 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.
+//
+// Note that this implementation is mirrored in withReverseContributionList,
+// so any changes should be reflected there (until these are combined).
 
 import {input, templateCompositeFrom} from '#composite';
 
@@ -7,6 +17,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: `withReverseReferenceList`,
 
@@ -28,14 +44,38 @@ export default templateCompositeFrom({
       dependencies: [input.myself(), input('data'), input('list')],
 
       compute: (continuation, {
-        [input.myself()]: thisThing,
+        [input.myself()]: myself,
         [input('data')]: data,
-        [input('list')]: refListProperty,
-      }) =>
-        continuation({
+        [input('list')]: list,
+      }) => {
+        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 referencedThing of referenceList) {
+              if (cacheRecord.has(referencedThing)) {
+                cacheRecord.get(referencedThing).push(referencingThing);
+              } else {
+                cacheRecord.set(referencedThing, [referencingThing]);
+              }
+            }
+          }
+
+          cache.set(data, cacheRecord);
+        }
+
+        return continuation({
           ['#reverseReferenceList']:
-            data.filter(thing => thing[refListProperty].includes(thisThing)),
-        }),
+            cache.get(data).get(myself) ?? [],
+        });
+      },
     },
   ],
 });