Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'config/helpers/incremental_webpack_compiler/history.js')
-rw-r--r--config/helpers/incremental_webpack_compiler/history.js176
1 files changed, 176 insertions, 0 deletions
diff --git a/config/helpers/incremental_webpack_compiler/history.js b/config/helpers/incremental_webpack_compiler/history.js
new file mode 100644
index 00000000000..24599900011
--- /dev/null
+++ b/config/helpers/incremental_webpack_compiler/history.js
@@ -0,0 +1,176 @@
+/* eslint-disable max-classes-per-file, no-underscore-dangle */
+
+const fs = require('fs');
+const log = require('./log');
+
+const ESSENTIAL_ENTRY_POINTS = [
+ // Login page
+ 'pages.sessions.new',
+ // Explore page
+ 'pages.root',
+];
+
+// TODO: Find a way to keep this list up-to-date/relevant.
+const COMMON_ENTRY_POINTS = [
+ ...ESSENTIAL_ENTRY_POINTS,
+ 'pages.admin',
+ 'pages.admin.dashboard',
+ 'pages.dashboard.groups.index',
+ 'pages.dashboard.projects.index',
+ 'pages.groups.new',
+ 'pages.groups.show',
+ 'pages.profiles.preferences.show',
+ 'pages.projects.commit.show',
+ 'pages.projects.edit',
+ 'pages.projects.issues.index',
+ 'pages.projects.issues.new',
+ 'pages.projects.issues.show',
+ 'pages.projects.jobs.show',
+ 'pages.projects.merge_requests.index',
+ 'pages.projects.merge_requests.show',
+ 'pages.projects.milestones.index',
+ 'pages.projects.new',
+ 'pages.projects.pipelines.index',
+ 'pages.projects.pipelines.show',
+ 'pages.projects.settings.ci_cd.show',
+ 'pages.projects.settings.repository.show',
+ 'pages.projects.show',
+ 'pages.users',
+];
+
+/**
+ * The History class is responsible for tracking which entry points have been
+ * requested, and persisting/loading the history to/from disk.
+ */
+class History {
+ constructor(historyFilePath) {
+ this._historyFilePath = historyFilePath;
+ this._history = {};
+
+ this._loadHistoryFile();
+ }
+
+ onRequestEntryPoint(entryPoint) {
+ const wasVisitedRecently = this.isRecentlyVisited(entryPoint);
+
+ this._addEntryPoint(entryPoint);
+
+ this._writeHistoryFile();
+
+ return wasVisitedRecently;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ isRecentlyVisited() {
+ return true;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ get size() {
+ return 0;
+ }
+
+ // Private methods
+
+ _addEntryPoint(entryPoint) {
+ if (!this._history[entryPoint]) {
+ this._history[entryPoint] = { lastVisit: null, count: 0 };
+ }
+
+ this._history[entryPoint].lastVisit = Date.now();
+ this._history[entryPoint].count += 1;
+ }
+
+ _writeHistoryFile() {
+ try {
+ fs.writeFileSync(this._historyFilePath, JSON.stringify(this._history), 'utf8');
+ } catch (error) {
+ log('Warning – Could not write to history', error.message);
+ }
+ }
+
+ _loadHistoryFile() {
+ try {
+ fs.accessSync(this._historyFilePath);
+ } catch (e) {
+ // History file doesn't exist; attempt to seed it, and return early
+ this._seedHistory();
+ return;
+ }
+
+ // History file already exists; attempt to load its contents into memory
+ try {
+ this._history = JSON.parse(fs.readFileSync(this._historyFilePath, 'utf8'));
+ const historySize = Object.keys(this._history).length;
+ log(`Successfully loaded history containing ${historySize} entry points`);
+ } catch (error) {
+ log('Could not load history', error.message);
+ }
+ }
+
+ /**
+ * Seeds a reasonable set of approximately the most common entry points to
+ * seed the history. This helps to avoid fresh GDK installs showing the
+ * compiling overlay too often.
+ */
+ _seedHistory() {
+ log('Seeding history...');
+ COMMON_ENTRY_POINTS.forEach((entryPoint) => this._addEntryPoint(entryPoint));
+ this._writeHistoryFile();
+ }
+}
+
+const MS_PER_DAY = 1000 * 60 * 60 * 24;
+
+/**
+ * The HistoryWithTTL class adds LRU-like behaviour onto the base History
+ * behaviour. Entry points visited within the last `ttl` days are considered
+ * "recent", and therefore should be eagerly compiled.
+ */
+class HistoryWithTTL extends History {
+ constructor(historyFilePath, ttl) {
+ super(historyFilePath);
+ this._ttl = ttl;
+ this._calculateRecentEntryPoints();
+ }
+
+ onRequestEntryPoint(entryPoint) {
+ const wasVisitedRecently = super.onRequestEntryPoint(entryPoint);
+
+ this._calculateRecentEntryPoints();
+
+ return wasVisitedRecently;
+ }
+
+ isRecentlyVisited(entryPoint) {
+ return this._recentEntryPoints.has(entryPoint);
+ }
+
+ get size() {
+ return this._recentEntryPoints.size;
+ }
+
+ // Private methods
+
+ _calculateRecentEntryPoints() {
+ const oldestVisitAllowed = Date.now() - MS_PER_DAY * this._ttl;
+
+ const recentEntryPoints = Object.entries(this._history).reduce(
+ (acc, [entryPoint, { lastVisit }]) => {
+ if (lastVisit > oldestVisitAllowed) {
+ acc.push(entryPoint);
+ }
+
+ return acc;
+ },
+ [],
+ );
+
+ this._recentEntryPoints = new Set([...ESSENTIAL_ENTRY_POINTS, ...recentEntryPoints]);
+ }
+}
+
+module.exports = {
+ History,
+ HistoryWithTTL,
+};