From 0a7f158b70a195ef57a2e6beb82862070c649f41 Mon Sep 17 00:00:00 2001
From: Lim Chee Aun <cheeaun@gmail.com>
Date: Sat, 14 Oct 2023 20:10:34 +0800
Subject: [PATCH] Memoize translated results

First step in migrating to moize
---
 package-lock.json                    | 39 ++++++++++++++++++++++++++++
 package.json                         |  1 +
 src/components/translation-block.jsx | 12 +++++++--
 src/utils/pmem.js                    |  5 ++++
 4 files changed, 55 insertions(+), 2 deletions(-)
 create mode 100644 src/utils/pmem.js

diff --git a/package-lock.json b/package-lock.json
index cc9b6087..2e2091d3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23,6 +23,7 @@
         "lz-string": "~1.5.0",
         "masto": "~6.3.1",
         "mem": "~9.0.2",
+        "moize": "~6.1.6",
         "p-retry": "~6.1.0",
         "p-throttle": "~5.1.0",
         "preact": "~10.18.1",
@@ -4295,6 +4296,11 @@
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
+    "node_modules/fast-equals": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-3.0.3.tgz",
+      "integrity": "sha512-NCe8qxnZFARSHGztGMZOO/PC1qa5MIFB5Hp66WdzbCRAz8U8US3bx1UTgLS49efBQPcUtO9gf5oVEY8o7y/7Kg=="
+    },
     "node_modules/fast-glob": {
       "version": "3.3.1",
       "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
@@ -5321,6 +5327,11 @@
         "node": ">= 8"
       }
     },
+    "node_modules/micro-memoize": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/micro-memoize/-/micro-memoize-4.1.2.tgz",
+      "integrity": "sha512-+HzcV2H+rbSJzApgkj0NdTakkC+bnyeiUxgT6/m7mjcz1CmM22KYFKp+EVj1sWe4UYcnriJr5uqHQD/gMHLD+g=="
+    },
     "node_modules/micromatch": {
       "version": "4.0.5",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
@@ -5378,6 +5389,15 @@
         "node": "*"
       }
     },
+    "node_modules/moize": {
+      "version": "6.1.6",
+      "resolved": "https://registry.npmjs.org/moize/-/moize-6.1.6.tgz",
+      "integrity": "sha512-vSKdIUO61iCmTqhdoIDrqyrtp87nWZUmBPniNjO0fX49wEYmyDO4lvlnFXiGcaH1JLE/s/9HbiK4LSHsbiUY6Q==",
+      "dependencies": {
+        "fast-equals": "^3.0.1",
+        "micro-memoize": "^4.1.2"
+      }
+    },
     "node_modules/ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -10525,6 +10545,11 @@
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
+    "fast-equals": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-3.0.3.tgz",
+      "integrity": "sha512-NCe8qxnZFARSHGztGMZOO/PC1qa5MIFB5Hp66WdzbCRAz8U8US3bx1UTgLS49efBQPcUtO9gf5oVEY8o7y/7Kg=="
+    },
     "fast-glob": {
       "version": "3.3.1",
       "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
@@ -11281,6 +11306,11 @@
       "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
       "dev": true
     },
+    "micro-memoize": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/micro-memoize/-/micro-memoize-4.1.2.tgz",
+      "integrity": "sha512-+HzcV2H+rbSJzApgkj0NdTakkC+bnyeiUxgT6/m7mjcz1CmM22KYFKp+EVj1sWe4UYcnriJr5uqHQD/gMHLD+g=="
+    },
     "micromatch": {
       "version": "4.0.5",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
@@ -11320,6 +11350,15 @@
         "brace-expansion": "^1.1.7"
       }
     },
+    "moize": {
+      "version": "6.1.6",
+      "resolved": "https://registry.npmjs.org/moize/-/moize-6.1.6.tgz",
+      "integrity": "sha512-vSKdIUO61iCmTqhdoIDrqyrtp87nWZUmBPniNjO0fX49wEYmyDO4lvlnFXiGcaH1JLE/s/9HbiK4LSHsbiUY6Q==",
+      "requires": {
+        "fast-equals": "^3.0.1",
+        "micro-memoize": "^4.1.2"
+      }
+    },
     "ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
diff --git a/package.json b/package.json
index dd07411b..7b78c254 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,7 @@
     "lz-string": "~1.5.0",
     "masto": "~6.3.1",
     "mem": "~9.0.2",
+    "moize": "~6.1.6",
     "p-retry": "~6.1.0",
     "p-throttle": "~5.1.0",
     "preact": "~10.18.1",
diff --git a/src/components/translation-block.jsx b/src/components/translation-block.jsx
index 234cd27c..06ce52de 100644
--- a/src/components/translation-block.jsx
+++ b/src/components/translation-block.jsx
@@ -7,6 +7,7 @@ import { useEffect, useRef, useState } from 'preact/hooks';
 import sourceLanguages from '../data/lingva-source-languages';
 import getTranslateTargetLanguage from '../utils/get-translate-target-language';
 import localeCode2Text from '../utils/localeCode2Text';
+import pmem from '../utils/pmem';
 
 import Icon from './icon';
 import Loader from './loader';
@@ -25,7 +26,7 @@ const LINGVA_INSTANCES = [
 ];
 let currentLingvaInstance = 0;
 
-function lingvaTranslate(text, source, target) {
+function _lingvaTranslate(text, source, target) {
   console.log('TRANSLATE', text, source, target);
   const fetchCall = () => {
     let instance = LINGVA_INSTANCES[currentLingvaInstance];
@@ -59,7 +60,14 @@ function lingvaTranslate(text, source, target) {
   //   lang: DEFAULT_LANG,
   // });
 }
-const throttledLingvaTranslate = throttle(lingvaTranslate);
+const TRANSLATED_MAX_AGE = 1000 * 60 * 60; // 1 hour
+const lingvaTranslate = pmem(_lingvaTranslate, {
+  maxAge: TRANSLATED_MAX_AGE,
+});
+const throttledLingvaTranslate = pmem(throttle(lingvaTranslate), {
+  // I know, this is double-layered memoization
+  maxAge: TRANSLATED_MAX_AGE,
+});
 
 function TranslationBlock({
   forceTranslate,
diff --git a/src/utils/pmem.js b/src/utils/pmem.js
new file mode 100644
index 00000000..8cd0be91
--- /dev/null
+++ b/src/utils/pmem.js
@@ -0,0 +1,5 @@
+import moize from 'moize';
+
+export default function pmem(fn, opts = {}) {
+  return moize(fn, { isPromise: true, ...opts, maxSize: Infinity });
+}