@appland/appmap 3.27.6 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,24 @@
1
1
  "use strict";
2
2
  const { createHash } = require('crypto');
3
- const { join: joinPath } = require('path');
3
+ const { join: joinPath, basename } = require('path');
4
4
  const fsp = require('fs').promises;
5
- const semver = require('semver');
6
5
  const { buildAppMap } = require('@appland/models');
7
- const writeFileAtomic = require('write-file-atomic');
6
+ const assert = require('assert');
8
7
  const { default: FileTooLargeError } = require('./fileTooLargeError');
9
- const { verbose, baseName, ctime } = require('../utils');
8
+ const { verbose, mtime } = require('../utils');
10
9
  const { algorithms, canonicalize } = require('./canonicalize');
10
+ const { default: AppMapIndex } = require('./appmapIndex');
11
11
  /**
12
12
  * CHANGELOG
13
13
  *
14
+ * # 1.1.3
15
+ *
16
+ * * Removed ctime file. Use mtime to determine when the AppMap was last updated.
17
+ * * Use higher precision for mtime.
18
+ *
14
19
  * # 1.1.2
15
20
  *
16
- * * Reject large appmaps instead of breaking randomly.
21
+ * * Reject large appmaps to avoid running out of system resources trying to process them.
17
22
  *
18
23
  * # 1.1.1
19
24
  *
@@ -26,7 +31,7 @@ const { algorithms, canonicalize } = require('./canonicalize');
26
31
  * * Fix handling of parent assignment in normalization.
27
32
  * * sql can contain the analysis (action, tables, columns), and/or the normalized query string.
28
33
  */
29
- const VERSION = '1.1.2';
34
+ const VERSION = '1.1.3';
30
35
  const MAX_APPMAP_SIZE = 50 * 1000 * 1000;
31
36
  class Fingerprinter {
32
37
  /**
@@ -41,93 +46,28 @@ class Fingerprinter {
41
46
  }
42
47
  // eslint-disable-next-line class-methods-use-this
43
48
  async fingerprint(appMapFileName) {
44
- const appMapCreatedAt = await ctime(appMapFileName);
45
- if (!appMapCreatedAt) {
46
- return;
47
- }
48
49
  if (verbose()) {
49
- console.warn(`Fingerprinting ${appMapFileName}`);
50
+ console.log(`Fingerprinting ${appMapFileName}`);
50
51
  }
51
- const indexDir = baseName(appMapFileName);
52
- const mtimeFileName = joinPath(indexDir, 'mtime');
53
- const versionFileName = joinPath(indexDir, 'version');
54
- const versionUpToDate = async () => {
55
- let versionStr = '0.0.1';
56
- try {
57
- versionStr = await fsp.readFile(versionFileName);
58
- }
59
- catch (err) {
60
- if (err.code !== 'ENOENT') {
61
- throw err;
62
- }
63
- }
64
- versionStr = versionStr.toString().trim();
65
- if (verbose()) {
66
- console.warn(`${appMapFileName} index version is ${versionStr}`);
67
- }
68
- return semver.satisfies(versionStr, `>= ${VERSION}`);
69
- };
70
- const indexUpToDate = async () => {
71
- let indexedAt = 0;
72
- try {
73
- const indexedAtStr = await fsp.readFile(mtimeFileName);
74
- indexedAt = parseInt(indexedAtStr, 10);
75
- }
76
- catch (err) {
77
- if (err.code !== 'ENOENT') {
78
- throw err;
79
- }
80
- }
81
- if (verbose()) {
82
- console.warn(`${appMapFileName} created at ${appMapCreatedAt}, indexed at ${indexedAt}`);
83
- }
84
- return indexedAt >= appMapCreatedAt;
85
- };
86
- if ((await versionUpToDate()) && (await indexUpToDate())) {
87
- if (verbose()) {
88
- console.warn('Fingerprint is up to date. Skipping...');
89
- }
52
+ const index = new AppMapIndex(appMapFileName);
53
+ if (!(await index.initialize())) {
90
54
  return;
91
55
  }
92
- {
93
- const stat = await fsp.stat(appMapFileName);
94
- if (stat.size > MAX_APPMAP_SIZE)
95
- throw new FileTooLargeError(appMapFileName, stat.size, MAX_APPMAP_SIZE);
96
- }
97
- let data;
98
- try {
99
- data = await fsp.readFile(appMapFileName);
100
- }
101
- catch (e) {
102
- if (e.code !== 'ENOENT') {
103
- console.warn(`${appMapFileName} does not exist. Skipping...`);
104
- return;
105
- }
106
- throw e;
107
- }
108
- if (verbose()) {
109
- console.warn(`Read ${data.length} bytes`);
110
- }
111
- let appmapData;
112
- try {
113
- // TODO: Should we normalize, compress, etc here?
114
- appmapData = JSON.parse(data.toString());
115
- }
116
- catch (err) {
117
- if (err instanceof SyntaxError) {
118
- // File may be in the process of writing.
119
- console.warn(`Error parsing JSON file ${appMapFileName} : ${err.message}`);
120
- return;
121
- }
122
- throw err;
123
- }
124
- if (!appmapData.metadata) {
56
+ if ((await index.versionUpToDate(VERSION)) &&
57
+ (await index.indexUpToDate())) {
125
58
  if (verbose()) {
126
- console.warn(`${appMapFileName} has no metadata. Skipping...`);
59
+ console.log('Fingerprint is up to date. Skipping...');
127
60
  }
128
61
  return;
129
62
  }
130
- const appmapDataWithoutMetadata = JSON.parse(data.toString());
63
+ if ((await index.appmapFileSize()) > MAX_APPMAP_SIZE)
64
+ throw new FileTooLargeError(appMapFileName, await index.appmapFileSize(), MAX_APPMAP_SIZE);
65
+ const appmapData = await index.loadAppMapData();
66
+ if (!appmapData)
67
+ return;
68
+ const appmapDataWithoutMetadata = await index.loadAppMapData();
69
+ if (!appmapDataWithoutMetadata)
70
+ return;
131
71
  delete appmapDataWithoutMetadata.metadata;
132
72
  const appmapDigest = createHash('sha256')
133
73
  .update(JSON.stringify(appmapDataWithoutMetadata, null, 2))
@@ -135,19 +75,16 @@ class Fingerprinter {
135
75
  const fingerprints = [];
136
76
  appmapData.metadata.fingerprints = fingerprints;
137
77
  const appmap = buildAppMap(appmapData).normalize().build();
138
- await fsp.mkdir(indexDir, { recursive: true });
78
+ await index.mkdir_p();
139
79
  await Promise.all(Object.keys(algorithms).map(async (algorithmName) => {
140
80
  const canonicalForm = canonicalize(algorithmName, appmap);
141
81
  const canonicalJSON = JSON.stringify(canonicalForm, null, 2);
142
82
  if (this.printCanonicalAppMaps) {
143
- await writeFileAtomic(joinPath(indexDir, `canonical.${algorithmName}.json`), canonicalJSON);
83
+ await index.writeFileAtomic(`canonical.${algorithmName}.json`, canonicalJSON);
144
84
  }
145
85
  const fingerprintDigest = createHash('sha256')
146
86
  .update(canonicalJSON)
147
87
  .digest('hex');
148
- if (verbose()) {
149
- console.warn(`Computed digest for ${algorithmName}`);
150
- }
151
88
  fingerprints.push({
152
89
  appmap_digest: appmapDigest,
153
90
  canonicalization_algorithm: algorithmName,
@@ -156,16 +93,20 @@ class Fingerprinter {
156
93
  });
157
94
  }));
158
95
  appmapData.metadata.fingerprints.sort((a, b) => a.canonicalization_algorithm.localeCompare(b.canonicalization_algorithm));
159
- await writeFileAtomic(appMapFileName, JSON.stringify(appmapData, null, 2));
160
- const appMapIndexedAt = await ctime(appMapFileName);
161
- await writeFileAtomic(joinPath(indexDir, 'ctime'), `${appMapCreatedAt}`);
162
- await writeFileAtomic(joinPath(indexDir, 'version'), VERSION);
163
- await writeFileAtomic(joinPath(indexDir, 'classMap.json'), JSON.stringify(appmap.classMap, null, 2));
164
- await writeFileAtomic(joinPath(indexDir, 'metadata.json'), JSON.stringify(appmap.metadata, null, 2));
165
- // NOTE: mtime needs to be written last.
166
- // Downstream code will watch for this file and assume
167
- // indexing is complete once it changes.
168
- await writeFileAtomic(joinPath(indexDir, 'mtime'), `${appMapIndexedAt}`);
96
+ const tempAppMapFileName = joinPath(index.indexDir, [basename(appMapFileName), 'tmp'].join('.'));
97
+ await index.writeFileAtomic(basename(tempAppMapFileName), JSON.stringify(appmap, null, 2));
98
+ const appMapIndexedAt = await mtime(tempAppMapFileName);
99
+ assert(appMapIndexedAt, `${tempAppMapFileName} should always exist and be a readable file`);
100
+ await Promise.all([
101
+ index.writeFileAtomic('version', VERSION),
102
+ index.writeFileAtomic('classMap.json', JSON.stringify(appmap.classMap, null, 2)),
103
+ index.writeFileAtomic('metadata.json', JSON.stringify(appmap.metadata, null, 2)),
104
+ index.writeFileAtomic('mtime', `${appMapIndexedAt}`),
105
+ ]);
106
+ // At this point, moving the AppMap file into place will trigger re-indexing.
107
+ // But the mtime will match the file modification time, so the algorithm will
108
+ // determine that the index is up-to-date.
109
+ await fsp.rename(tempAppMapFileName, appMapFileName, { overwrite: true });
169
110
  this.counterFn();
170
111
  }
171
112
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fingerprinter.js","sourceRoot":"","sources":["../../src/fingerprint/fingerprinter.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fingerprinter.js","sourceRoot":"","sources":["../../src/fingerprint/fingerprinter.js"],"names":[],"mappings":"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"}