Add new Server.resources object, which basically keeps weak references to anything...
authorNick Downing <nick@ndcode.org>
Sun, 2 Dec 2018 05:22:50 +0000 (16:22 +1100)
committerNick Downing <nick@ndcode.org>
Sun, 2 Dec 2018 05:22:50 +0000 (16:22 +1100)
Resources.js [new file with mode: 0644]
Server.js
SiteConfig.js [new file with mode: 0644]
SiteDefault.js [deleted file]
SiteRoot.js
_config/server.jst
index.js

diff --git a/Resources.js b/Resources.js
new file mode 100644 (file)
index 0000000..9041d73
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 Nick Downing <nick@ndcode.org>
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+let Resources = function(diag) {
+  if (!this instanceof Resources)
+    throw new Error('Resources is a constructor')
+  this.map = new Map()
+  this.diag = diag || false
+}
+
+Resources.prototype.ref = function(key, factory_func) {
+  if (this.diag)
+    console.log(`ref ${key}`)
+  result = this.map.get(key)
+  if (result === undefined) {
+    result = {refs: 0, value: factory_func()}
+    this.map.set(key, result)
+  }
+  result.refs += 1
+  return result.value
+}
+
+Resources.prototype.unref = function(key) {
+  if (this.diag)
+    console.log(`unref ${key}`)
+  result = this.map.get(key)
+  assert(result !== undefined && result.refs > 0)
+  result.refs -= 1
+  if (result.refs === 0)
+    this.map.del(key)
+}
+
+module.exports = Resources
index c358648..65dae19 100644 (file)
--- a/Server.js
+++ b/Server.js
@@ -1,4 +1,5 @@
 let JSTCache = require('@ndcode/jst_cache')
+let Resources = require('./Resources')
 let Site = require('./Site')
 let assert = require('assert')
 let fs = require('fs')
@@ -20,7 +21,15 @@ let Server = function() {
   this.mime_type_html = 'text/html; charset=utf-8'
   this.mime_type_default = 'application/octet-stream'
 
-  this.jst_cache = new JSTCache('.', {_jst_server: jst_server}, true)
+  this.resources = new Resources()
+  this.resources_jst_cache = this.resources.ref(
+    'jst_cache',
+    () => new Resources()
+  )
+  this.jst_cache = this.resources_jst_cache.ref(
+    '.',
+    () => new JSTCache('.', {_jst_server: jst_server}, true)
+  )
 }
 
 let compare_listen = (a, b) => {
diff --git a/SiteConfig.js b/SiteConfig.js
new file mode 100644 (file)
index 0000000..7041ab4
--- /dev/null
@@ -0,0 +1,34 @@
+let JSTCache = require('@ndcode/jst_cache')
+let Site = require('./Site')
+let jst_server = require('./index')
+
+let SiteConfig = function(server, root) {
+  if (!this instanceof SiteConfig)
+    throw new Error('SiteConfig is a constructor')
+  Site.call(this, server)
+  this.root = root
+
+  this.resources_jst_cache = server.resources.ref(
+    'jst_cache',
+    () => new Resources()
+  )
+  this.jst_cache = this.resources_jst_cache.ref(
+    root,
+    () => new JSTCache(root, {_jst_server: jst_server}, true)
+  )
+  this.site = undefined
+}
+
+SiteConfig.prototype = Object.create(Site.prototype)
+
+SiteConfig.prototype.respond = async function(env) {
+  let config = await this.jst_cache.get(
+    this.root + '/_config/site.jst',
+    true
+  )
+  if (config !== undefined)
+    this.site = await config(this.server, this.root, this.site)
+  return this.site.respond(env)
+}
+
+module.exports = SiteConfig
diff --git a/SiteDefault.js b/SiteDefault.js
deleted file mode 100644 (file)
index 7c8c7fc..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-let SiteRoot = require('./SiteRoot')
-
-let SiteDefault = function(server, root) {
-  if (!this instanceof SiteDefault)
-    throw new Error('SiteDefault is a constructor')
-  SiteRoot.call(this, server, root)
-  this.site = undefined
-}
-
-SiteDefault.prototype = Object.create(SiteRoot.prototype)
-
-SiteDefault.prototype.respond = async function(env) {
-  let config
-  try {
-    config = await this.get_jst('/_config/site.jst', true)
-  }
-  catch (err) {
-    if (!(err instanceof Error) || err.code !== 'ENOENT')
-      throw err
-    // no custom site object, handle the request ourselves
-    return SiteRoot.prototype.respond.call(this, env)
-  }
-  if (config !== undefined)
-    this.site = await config(this.server, this.root, this.site)
-  return this.site.respond(env)
-}
-
-module.exports = SiteDefault
index b215ee3..45b2687 100644 (file)
@@ -6,6 +6,7 @@ let MinCSSCache = require('@ndcode/min_css_cache')
 let MinJSCache = require('@ndcode/min_js_cache')
 let MinHTMLCache = require('@ndcode/min_html_cache')
 let MinSVGCache = require('@ndcode/min_svg_cache')
+let Resources = require('./Resources')
 let Site = require('./Site')
 let TextCache = require('@ndcode/text_cache')
 let ZipCache = require('@ndcode/zip_cache')
@@ -26,7 +27,14 @@ let SiteRoot = function(server, root) {
 
   this.json_cache = new JSONCache(true)
   this.json_cache_rw = new JSONCacheRW(true)
-  this.jst_cache = new JSTCache(root, {_jst_server: jst_server}, true)
+  this.resources_jst_cache = server.resources.ref(
+    'jst_cache',
+    () => new Resources()
+  )
+  this.jst_cache = server.resources_jst_cache.ref(
+    root,
+    () => new JSTCache(root, {_jst_server: jst_server}, true)
+  )
   this.less_css_cache = new LessCSSCache(root, true)
   this.min_css_cache = new MinCSSCache(true)
   this.min_js_cache = new MinJSCache(true)
index d59f9eb..542bb8e 100644 (file)
@@ -18,7 +18,7 @@ return async server => (
       ".xml": "text/xml; charset=utf-8"
     },
     sites: {
-      'localhost': new _jst_server.SiteDefault(server, 'site'),
+      'localhost': new _jst_server.SiteRoot(server, 'site'),
       'localhost.localdomain': new _jst_server.SiteRedirect(server, 'localhost')
     }
   }
index 34b1f94..80ee574 100644 (file)
--- a/index.js
+++ b/index.js
@@ -1,5 +1,6 @@
+exports.Resources = require('./Resources')
 exports.Server = require('./Server')
 exports.Site = require('./Site')
-exports.SiteDefault = require('./SiteDefault')
+exports.SiteConfig = require('./SiteConfig')
 exports.SiteRedirect = require('./SiteRedirect')
 exports.SiteRoot = require('./SiteRoot')