5 <title>JSDoc: Source: BuildCache.js</title>
7 <script src="scripts/prettify/prettify.js"> </script>
8 <script src="scripts/prettify/lang-css.js"> </script>
10 <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
12 <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
13 <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
20 <h1 class="page-title">Source: BuildCache.js</h1>
29 <pre class="prettyprint source linenums"><code>/*
30 * Copyright (C) 2018 Nick Downing <nick@ndcode.org>
31 * SPDX-License-Identifier: MIT
33 * Permission is hereby granted, free of charge, to any person obtaining a copy
34 * of this software and associated documentation files (the "Software"), to
35 * deal in the Software without restriction, including without limitation the
36 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
37 * sell copies of the Software, and to permit persons to whom the Software is
38 * furnished to do so, subject to the following conditions:
40 * The above copyright notice and this permission notice shall be included in
41 * all copies or substantial portions of the Software.
43 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
48 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
52 let fs = require('fs')
53 let util = require('util')
55 let fs_stat = util.promisify(fs.stat)
58 * Constructs a cache object. The cache object is intended to store objects of
59 * arbitrary JavaScript type, which are built from on-disk source files of some
60 * kind. The cache tracks the source files of each object, and makes sure the
61 * objects are rebuilt as required if the source files change on disk.
64 * @param {boolean} diag - Should diagnostic messages be printed to the
67 let BuildCache = function(diag) {
68 if (!this instanceof BuildCache)
69 throw new Error('BuildCache is a constructor')
71 this.diag = diag || false
75 * Abstract method which is expected to build and return an object, given its
76 * key. Called from "get()" when the object does not exist or is out of date.
78 * If this method throws an exception, the key will be deleted from the cache
79 * and the exception re-thrown to the caller of "get()". If there are multiple
80 * callers to "get()" blocking and waiting for the build, they all receive the
81 * same exception object. So one has to be careful the exception is shareable.
84 * @param {string} key - Usually the path to the main source file on disk.
85 * @param {object} result - A dictionary to receive information about the built
86 * object, you can optionally set "result.deps" to a list of dependency files
87 * whose modification would invalidate the just-built and cached object.
89 BuildCache.prototype.build = async function(key, result) {
90 throw new Error('not implemented')
94 * Retrieves the object stored in the cache under "key". If "key" already
95 * exists in the cache, then it will be checked for up-to-dateness. If present
96 * and up-to-date then its object is returned directly. Otherwise the abstract
97 * "build()" method is called to attempt to build the object, and either an
98 * exception is thrown or the built object is stored and return to the caller.
100 * Other callers requsting the same object while the original build progresses
101 * will be blocked, and all will wait for the build to complete. In this time,
102 * no new up-to-date check will be initiated. But as soon as the build is
103 * completed and the cache updated, further up-to-date checks become possible.
105 * An interesting alternate usage is provided for objects whose contents only
106 * matter if they have been rebuilt since last time. For example, suppose we
107 * want to periodically read a configuration file, and then possibly restart
108 * some long-running process if the configuration has changed. Then it is not
109 * necessary to store the result of configuration parsing in the cache, since
110 * it is only needed momentarily (while we're actually restarting the process).
111 * In such case, pass "once = true" and an "undefined" return means no change.
114 * @param {string} key - Usually the path to the main source file on disk.
115 * @param {boolean} once - If "true", it means the returned object will only be
116 * used once. See above for a more comprehensive discussion of this feature.
118 BuildCache.prototype.get = async function(key, once) {
119 let result = this.map.get(key)
120 if (result === undefined) {
122 console.log(`building ${key}`)
123 result = {deps: [key], time: Date.now()}
124 result.done = this.build(key, result)
125 this.map.set(key, result)
136 else if (result.done === undefined) {
138 console.log(`checking ${key}`)
141 for (let i = 0; i < result.deps.length; ++i) {
144 stats = await fs_stat(result.deps[i])
147 if (!(err instanceof Error) || err.code !== 'ENOENT')
151 if (stats === undefined || stats.mtimeMs > result.time) {
153 console.log(`rebuilding ${key} reason ${result.deps[i]}`)
155 result.time = Date.now()
156 await this.build(key, result)
174 let value = result.value
176 result.value = undefined
181 * Call this periodically to allow the cache to clean itself of stale objects.
182 * It can be called as often as convenient, but since the cache can be large,
183 * the frequency of calls to "kick()" should be kept low. For example, if
184 * unreferenced objects should be kept for one day, then call "kick()" once
185 * per hour, and the actual lifetime will be at least 24 and up to 25 hours.
187 * The cache cleaning is not yet implemented, but the dummy "kick()" function
188 * is provided so that you can start to put the cleaning infrastructure in your
189 * code already. The constructor arguments might change later for this feature.
193 BuildCache.prototype.kick = function() {
194 // not yet implemented
197 module.exports = BuildCache
208 <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="BuildCache.html">BuildCache</a></li></ul>
214 Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.3</a> on Wed Feb 05 2020 00:11:43 GMT+1100 (Australian Eastern Daylight Time)
217 <script> prettyPrint(); </script>
218 <script src="scripts/linenumber.js"> </script>