@commitspark/graphql-api 1.0.0-beta.9 → 2.0.0-beta.1

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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.0.0-beta.1] - 2026-09-24
9
+
10
+ ### Changed
11
+
12
+ - Cache entry content by content hash across commits so that only changed entries are retrieved from Git adapters
13
+ after a commit changes
14
+ - Upgrade to @commitspark/git-adapter 2.0.0-beta.1, which requires Git adapters of major version 2
15
+
16
+ ## [1.0.0] - 2026-02-27
17
+
18
+ ### Changed
19
+
20
+ - Upgrade to @commitspark/git-adapter 1.0.0
21
+
8
22
  ## [1.0.0-beta.9] - 2026-02-26
9
23
 
10
24
  ### Fixed
package/README.md CHANGED
@@ -22,10 +22,10 @@ There are two common ways to use this library:
22
22
  ```shell
23
23
  npm i @commitspark/graphql-api
24
24
  ```
25
- 2. By making GraphQL calls over HTTP to this library wrapped in a webserver or Lambda function of choice.
25
+ 2. By making GraphQL calls over HTTP to this library wrapped in a webserver or Lambda function.
26
26
 
27
- Please see the [Node.js Express server example](https://github.com/commitspark/example-http-express)
28
- or [Lambda function example](https://github.com/commitspark/example-code-serverless) for details.
27
+ You can find an example Node.js Express web server implementation
28
+ [here](https://github.com/commitspark/example-http-express).
29
29
 
30
30
  ## Installing Git provider support
31
31
 
@@ -5,66 +5,104 @@ const git_adapter_1 = require("@commitspark/git-adapter");
5
5
  const errors_ts_1 = require("../graphql/errors.js");
6
6
  const MAX_CACHE_ENTRIES = 50;
7
7
  // intentionally not async so that the same in-flight promise is returned to all callers
8
- const getEntriesRecordByRef = (entriesCache, inflightEntries, cacheSize, context, ref) => {
8
+ const getEntriesRecordByRef = (entriesCache, contentCache, inflightEntries, cacheSize, context, ref) => {
9
9
  const cacheRecord = entriesCache.get(ref);
10
10
  if (cacheRecord !== undefined) {
11
11
  // move map key back to end of list (newest)
12
12
  entriesCache.delete(ref);
13
13
  entriesCache.set(ref, cacheRecord);
14
- return Promise.resolve(cacheRecord);
14
+ return Promise.resolve(cacheRecord.entriesRecord);
15
15
  }
16
16
  const inflightPromise = inflightEntries.get(ref);
17
17
  if (inflightPromise) {
18
18
  return inflightPromise;
19
19
  }
20
- const fetchPromise = fetchAndCacheEntries(entriesCache, cacheSize, context, ref).finally(() => inflightEntries.delete(ref));
20
+ const fetchPromise = fetchAndCacheEntries(entriesCache, contentCache, cacheSize, context, ref).finally(() => inflightEntries.delete(ref));
21
21
  inflightEntries.set(ref, fetchPromise);
22
22
  return fetchPromise;
23
23
  };
24
- const fetchAndCacheEntries = async (entriesCache, cacheSize, context, ref) => {
25
- let allEntries;
26
- try {
27
- allEntries = await context.gitAdapter.getEntries(ref);
24
+ const fetchAndCacheEntries = async (entriesCache, contentCache, cacheSize, context, ref) => {
25
+ const entryHashes = await callGitAdapter(() => context.gitAdapter.getEntryHashes(ref));
26
+ // hold on to known content now, as it may be evicted from the content cache while missing content is fetched
27
+ const contentByHash = new Map();
28
+ const idsToFetchByHash = new Map();
29
+ for (const { id, hash } of entryHashes) {
30
+ const content = contentCache.get(hash);
31
+ if (content !== undefined) {
32
+ contentByHash.set(hash, content);
33
+ }
34
+ else if (!idsToFetchByHash.has(hash)) {
35
+ // entries with equal hash have equal content, so fetching one of them is sufficient
36
+ idsToFetchByHash.set(hash, id);
37
+ }
28
38
  }
29
- catch (err) {
30
- if (err instanceof git_adapter_1.GitAdapterError) {
31
- throw (0, errors_ts_1.createError)(err.message, err.code, {});
39
+ if (idsToFetchByHash.size > 0) {
40
+ const fetchedEntries = await callGitAdapter(() => context.gitAdapter.getEntriesByIds(ref, [...idsToFetchByHash.values()]));
41
+ const fetchedEntriesById = new Map(fetchedEntries.map((entry) => [entry.id, entry]));
42
+ for (const [hash, id] of idsToFetchByHash) {
43
+ const fetchedEntry = fetchedEntriesById.get(id);
44
+ if (fetchedEntry === undefined) {
45
+ throw (0, errors_ts_1.createError)(`Git adapter did not return requested entry "${id}".`, "INTERNAL_ERROR" /* ErrorCode.INTERNAL_ERROR */, {});
46
+ }
47
+ contentByHash.set(hash, createEntryContent(fetchedEntry));
32
48
  }
33
- const message = err instanceof Error ? err.message : String(err);
34
- throw (0, errors_ts_1.createError)(message, "INTERNAL_ERROR" /* ErrorCode.INTERNAL_ERROR */, {});
35
49
  }
36
- const entriesById = new Map(allEntries.map((entry) => [entry.id, entry]));
50
+ const entriesById = new Map();
37
51
  const entriesByType = new Map();
38
- for (const entry of allEntries) {
52
+ for (const { id, hash } of entryHashes) {
53
+ const entry = {
54
+ id: id,
55
+ ...contentByHash.get(hash),
56
+ };
57
+ entriesById.set(id, entry);
39
58
  const existingEntriesOfType = entriesByType.get(entry.metadata.type) || [];
40
59
  existingEntriesOfType.push(entry);
41
60
  entriesByType.set(entry.metadata.type, existingEntriesOfType);
42
61
  }
43
62
  const newCacheRecord = {
44
- byType: entriesByType,
45
- byId: entriesById,
63
+ entriesRecord: {
64
+ byType: entriesByType,
65
+ byId: entriesById,
66
+ },
67
+ contentHashes: [...contentByHash.keys()],
46
68
  };
69
+ for (const [hash, content] of contentByHash) {
70
+ contentCache.set(hash, content);
71
+ }
47
72
  entriesCache.set(ref, newCacheRecord);
48
73
  if (entriesCache.size > cacheSize) {
49
74
  // get first map key (oldest)
50
75
  const oldestKey = entriesCache.keys().next().value;
51
76
  if (oldestKey !== undefined) {
52
77
  entriesCache.delete(oldestKey);
78
+ removeUnreferencedContent(entriesCache, contentCache);
53
79
  }
54
80
  }
55
- return newCacheRecord;
81
+ return newCacheRecord.entriesRecord;
56
82
  };
57
- const getSchemaStringByRef = async (schemaCache, cacheSize, context, ref) => {
58
- const schemaCacheRecord = schemaCache.get(ref);
59
- if (schemaCacheRecord !== undefined) {
60
- // move map key back to end of list (newest)
61
- schemaCache.delete(ref);
62
- schemaCache.set(ref, schemaCacheRecord);
63
- return schemaCacheRecord;
83
+ const createEntryContent = (entry) => {
84
+ const content = { metadata: entry.metadata };
85
+ if (entry.data !== undefined) {
86
+ content.data = entry.data;
64
87
  }
65
- let schemaString;
88
+ return content;
89
+ };
90
+ const removeUnreferencedContent = (entriesCache, contentCache) => {
91
+ const referencedHashes = new Set();
92
+ for (const cacheRecord of entriesCache.values()) {
93
+ for (const hash of cacheRecord.contentHashes) {
94
+ referencedHashes.add(hash);
95
+ }
96
+ }
97
+ for (const hash of contentCache.keys()) {
98
+ if (!referencedHashes.has(hash)) {
99
+ contentCache.delete(hash);
100
+ }
101
+ }
102
+ };
103
+ const callGitAdapter = async (operation) => {
66
104
  try {
67
- schemaString = await context.gitAdapter.getSchema(ref);
105
+ return await operation();
68
106
  }
69
107
  catch (err) {
70
108
  if (err instanceof git_adapter_1.GitAdapterError) {
@@ -73,6 +111,16 @@ const getSchemaStringByRef = async (schemaCache, cacheSize, context, ref) => {
73
111
  const message = err instanceof Error ? err.message : String(err);
74
112
  throw (0, errors_ts_1.createError)(message, "INTERNAL_ERROR" /* ErrorCode.INTERNAL_ERROR */, {});
75
113
  }
114
+ };
115
+ const getSchemaStringByRef = async (schemaCache, cacheSize, context, ref) => {
116
+ const schemaCacheRecord = schemaCache.get(ref);
117
+ if (schemaCacheRecord !== undefined) {
118
+ // move map key back to end of list (newest)
119
+ schemaCache.delete(ref);
120
+ schemaCache.set(ref, schemaCacheRecord);
121
+ return schemaCacheRecord;
122
+ }
123
+ const schemaString = await callGitAdapter(() => context.gitAdapter.getSchema(ref));
76
124
  schemaCache.set(ref, schemaString);
77
125
  if (schemaCache.size > cacheSize) {
78
126
  // get first map key (oldest)
@@ -85,10 +133,11 @@ const getSchemaStringByRef = async (schemaCache, cacheSize, context, ref) => {
85
133
  };
86
134
  const createCacheHandler = (cacheSize = MAX_CACHE_ENTRIES) => {
87
135
  const entriesCache = new Map();
136
+ const contentCache = new Map();
88
137
  const schemaCache = new Map();
89
138
  const inflightEntries = new Map();
90
139
  return {
91
- getEntriesRecord: (...args) => getEntriesRecordByRef(entriesCache, inflightEntries, cacheSize, ...args),
140
+ getEntriesRecord: (...args) => getEntriesRecordByRef(entriesCache, contentCache, inflightEntries, cacheSize, ...args),
92
141
  getSchema: (...args) => getSchemaStringByRef(schemaCache, cacheSize, ...args),
93
142
  };
94
143
  };
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/persistence/cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/persistence/cache.ts"],"names":[],"mappings":"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"}
@@ -2,66 +2,104 @@ import { GitAdapterError } from '@commitspark/git-adapter';
2
2
  import { createError } from "../graphql/errors.js";
3
3
  const MAX_CACHE_ENTRIES = 50;
4
4
  // intentionally not async so that the same in-flight promise is returned to all callers
5
- const getEntriesRecordByRef = (entriesCache, inflightEntries, cacheSize, context, ref) => {
5
+ const getEntriesRecordByRef = (entriesCache, contentCache, inflightEntries, cacheSize, context, ref) => {
6
6
  const cacheRecord = entriesCache.get(ref);
7
7
  if (cacheRecord !== undefined) {
8
8
  // move map key back to end of list (newest)
9
9
  entriesCache.delete(ref);
10
10
  entriesCache.set(ref, cacheRecord);
11
- return Promise.resolve(cacheRecord);
11
+ return Promise.resolve(cacheRecord.entriesRecord);
12
12
  }
13
13
  const inflightPromise = inflightEntries.get(ref);
14
14
  if (inflightPromise) {
15
15
  return inflightPromise;
16
16
  }
17
- const fetchPromise = fetchAndCacheEntries(entriesCache, cacheSize, context, ref).finally(() => inflightEntries.delete(ref));
17
+ const fetchPromise = fetchAndCacheEntries(entriesCache, contentCache, cacheSize, context, ref).finally(() => inflightEntries.delete(ref));
18
18
  inflightEntries.set(ref, fetchPromise);
19
19
  return fetchPromise;
20
20
  };
21
- const fetchAndCacheEntries = async (entriesCache, cacheSize, context, ref) => {
22
- let allEntries;
23
- try {
24
- allEntries = await context.gitAdapter.getEntries(ref);
21
+ const fetchAndCacheEntries = async (entriesCache, contentCache, cacheSize, context, ref) => {
22
+ const entryHashes = await callGitAdapter(() => context.gitAdapter.getEntryHashes(ref));
23
+ // hold on to known content now, as it may be evicted from the content cache while missing content is fetched
24
+ const contentByHash = new Map();
25
+ const idsToFetchByHash = new Map();
26
+ for (const { id, hash } of entryHashes) {
27
+ const content = contentCache.get(hash);
28
+ if (content !== undefined) {
29
+ contentByHash.set(hash, content);
30
+ }
31
+ else if (!idsToFetchByHash.has(hash)) {
32
+ // entries with equal hash have equal content, so fetching one of them is sufficient
33
+ idsToFetchByHash.set(hash, id);
34
+ }
25
35
  }
26
- catch (err) {
27
- if (err instanceof GitAdapterError) {
28
- throw createError(err.message, err.code, {});
36
+ if (idsToFetchByHash.size > 0) {
37
+ const fetchedEntries = await callGitAdapter(() => context.gitAdapter.getEntriesByIds(ref, [...idsToFetchByHash.values()]));
38
+ const fetchedEntriesById = new Map(fetchedEntries.map((entry) => [entry.id, entry]));
39
+ for (const [hash, id] of idsToFetchByHash) {
40
+ const fetchedEntry = fetchedEntriesById.get(id);
41
+ if (fetchedEntry === undefined) {
42
+ throw createError(`Git adapter did not return requested entry "${id}".`, "INTERNAL_ERROR" /* ErrorCode.INTERNAL_ERROR */, {});
43
+ }
44
+ contentByHash.set(hash, createEntryContent(fetchedEntry));
29
45
  }
30
- const message = err instanceof Error ? err.message : String(err);
31
- throw createError(message, "INTERNAL_ERROR" /* ErrorCode.INTERNAL_ERROR */, {});
32
46
  }
33
- const entriesById = new Map(allEntries.map((entry) => [entry.id, entry]));
47
+ const entriesById = new Map();
34
48
  const entriesByType = new Map();
35
- for (const entry of allEntries) {
49
+ for (const { id, hash } of entryHashes) {
50
+ const entry = {
51
+ id: id,
52
+ ...contentByHash.get(hash),
53
+ };
54
+ entriesById.set(id, entry);
36
55
  const existingEntriesOfType = entriesByType.get(entry.metadata.type) || [];
37
56
  existingEntriesOfType.push(entry);
38
57
  entriesByType.set(entry.metadata.type, existingEntriesOfType);
39
58
  }
40
59
  const newCacheRecord = {
41
- byType: entriesByType,
42
- byId: entriesById,
60
+ entriesRecord: {
61
+ byType: entriesByType,
62
+ byId: entriesById,
63
+ },
64
+ contentHashes: [...contentByHash.keys()],
43
65
  };
66
+ for (const [hash, content] of contentByHash) {
67
+ contentCache.set(hash, content);
68
+ }
44
69
  entriesCache.set(ref, newCacheRecord);
45
70
  if (entriesCache.size > cacheSize) {
46
71
  // get first map key (oldest)
47
72
  const oldestKey = entriesCache.keys().next().value;
48
73
  if (oldestKey !== undefined) {
49
74
  entriesCache.delete(oldestKey);
75
+ removeUnreferencedContent(entriesCache, contentCache);
50
76
  }
51
77
  }
52
- return newCacheRecord;
78
+ return newCacheRecord.entriesRecord;
53
79
  };
54
- const getSchemaStringByRef = async (schemaCache, cacheSize, context, ref) => {
55
- const schemaCacheRecord = schemaCache.get(ref);
56
- if (schemaCacheRecord !== undefined) {
57
- // move map key back to end of list (newest)
58
- schemaCache.delete(ref);
59
- schemaCache.set(ref, schemaCacheRecord);
60
- return schemaCacheRecord;
80
+ const createEntryContent = (entry) => {
81
+ const content = { metadata: entry.metadata };
82
+ if (entry.data !== undefined) {
83
+ content.data = entry.data;
61
84
  }
62
- let schemaString;
85
+ return content;
86
+ };
87
+ const removeUnreferencedContent = (entriesCache, contentCache) => {
88
+ const referencedHashes = new Set();
89
+ for (const cacheRecord of entriesCache.values()) {
90
+ for (const hash of cacheRecord.contentHashes) {
91
+ referencedHashes.add(hash);
92
+ }
93
+ }
94
+ for (const hash of contentCache.keys()) {
95
+ if (!referencedHashes.has(hash)) {
96
+ contentCache.delete(hash);
97
+ }
98
+ }
99
+ };
100
+ const callGitAdapter = async (operation) => {
63
101
  try {
64
- schemaString = await context.gitAdapter.getSchema(ref);
102
+ return await operation();
65
103
  }
66
104
  catch (err) {
67
105
  if (err instanceof GitAdapterError) {
@@ -70,6 +108,16 @@ const getSchemaStringByRef = async (schemaCache, cacheSize, context, ref) => {
70
108
  const message = err instanceof Error ? err.message : String(err);
71
109
  throw createError(message, "INTERNAL_ERROR" /* ErrorCode.INTERNAL_ERROR */, {});
72
110
  }
111
+ };
112
+ const getSchemaStringByRef = async (schemaCache, cacheSize, context, ref) => {
113
+ const schemaCacheRecord = schemaCache.get(ref);
114
+ if (schemaCacheRecord !== undefined) {
115
+ // move map key back to end of list (newest)
116
+ schemaCache.delete(ref);
117
+ schemaCache.set(ref, schemaCacheRecord);
118
+ return schemaCacheRecord;
119
+ }
120
+ const schemaString = await callGitAdapter(() => context.gitAdapter.getSchema(ref));
73
121
  schemaCache.set(ref, schemaString);
74
122
  if (schemaCache.size > cacheSize) {
75
123
  // get first map key (oldest)
@@ -82,10 +130,11 @@ const getSchemaStringByRef = async (schemaCache, cacheSize, context, ref) => {
82
130
  };
83
131
  export const createCacheHandler = (cacheSize = MAX_CACHE_ENTRIES) => {
84
132
  const entriesCache = new Map();
133
+ const contentCache = new Map();
85
134
  const schemaCache = new Map();
86
135
  const inflightEntries = new Map();
87
136
  return {
88
- getEntriesRecord: (...args) => getEntriesRecordByRef(entriesCache, inflightEntries, cacheSize, ...args),
137
+ getEntriesRecord: (...args) => getEntriesRecordByRef(entriesCache, contentCache, inflightEntries, cacheSize, ...args),
89
138
  getSchema: (...args) => getSchemaStringByRef(schemaCache, cacheSize, ...args),
90
139
  };
91
140
  };
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/persistence/cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/persistence/cache.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/persistence/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAmB,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAQ5C,UAAU,aAAa;IACrB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IACxB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;CAC7B;AAED,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE,CAChB,OAAO,EAAE,aAAa,EACtB,GAAG,EAAE,MAAM,KACR,OAAO,CAAC,aAAa,CAAC,CAAA;IAC3B,SAAS,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACpE;AAwHD,eAAO,MAAM,kBAAkB,GAC7B,YAAW,MAA0B,KACpC,sBAaF,CAAA"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/persistence/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAmB,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAY5C,UAAU,aAAa;IACrB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IACxB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;CAC7B;AAOD,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE,CAChB,OAAO,EAAE,aAAa,EACtB,GAAG,EAAE,MAAM,KACR,OAAO,CAAC,aAAa,CAAC,CAAA;IAC3B,SAAS,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACpE;AA+LD,eAAO,MAAM,kBAAkB,GAC7B,YAAW,MAA0B,KACpC,sBAoBF,CAAA"}
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "gitops",
10
10
  "api"
11
11
  ],
12
- "version": "1.0.0-beta.9",
12
+ "version": "2.0.0-beta.1",
13
13
  "license": "ISC",
14
14
  "private": false,
15
15
  "files": [
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@apollo/server": "^5.2.0",
47
- "@commitspark/git-adapter": "^0.30.0",
47
+ "@commitspark/git-adapter": "^2.0.0-beta.1",
48
48
  "@graphql-tools/schema": "^9.0.0",
49
49
  "@graphql-tools/utils": "^9.0.0"
50
50
  },
@@ -3,7 +3,11 @@ import { ApolloContext } from '../client.ts'
3
3
  import { createError, ErrorCode } from '../graphql/errors.ts'
4
4
 
5
5
  type Ref = string
6
- type EntriesCache = Map<Ref, EntriesRecord>
6
+ type ContentHash = string
7
+ type EntryContent = Omit<Entry, 'id'>
8
+ type EntriesCache = Map<Ref, CommitCacheRecord>
9
+ // entry content shared across all cached commits, so that unchanged entries are neither fetched nor stored twice
10
+ type ContentCache = Map<ContentHash, EntryContent>
7
11
  type SchemaCache = Map<Ref, string>
8
12
  type InflightEntries = Map<Ref, Promise<EntriesRecord>>
9
13
 
@@ -12,6 +16,11 @@ interface EntriesRecord {
12
16
  byType: Map<string, Entry[]>
13
17
  }
14
18
 
19
+ interface CommitCacheRecord {
20
+ entriesRecord: EntriesRecord
21
+ contentHashes: ContentHash[]
22
+ }
23
+
15
24
  export interface RepositoryCacheHandler {
16
25
  getEntriesRecord: (
17
26
  context: ApolloContext,
@@ -25,6 +34,7 @@ const MAX_CACHE_ENTRIES = 50
25
34
  // intentionally not async so that the same in-flight promise is returned to all callers
26
35
  const getEntriesRecordByRef = (
27
36
  entriesCache: EntriesCache,
37
+ contentCache: ContentCache,
28
38
  inflightEntries: InflightEntries,
29
39
  cacheSize: number,
30
40
  context: ApolloContext,
@@ -36,7 +46,7 @@ const getEntriesRecordByRef = (
36
46
  entriesCache.delete(ref)
37
47
  entriesCache.set(ref, cacheRecord)
38
48
 
39
- return Promise.resolve(cacheRecord)
49
+ return Promise.resolve(cacheRecord.entriesRecord)
40
50
  }
41
51
 
42
52
  const inflightPromise = inflightEntries.get(ref)
@@ -46,6 +56,7 @@ const getEntriesRecordByRef = (
46
56
 
47
57
  const fetchPromise = fetchAndCacheEntries(
48
58
  entriesCache,
59
+ contentCache,
49
60
  cacheSize,
50
61
  context,
51
62
  ref,
@@ -58,34 +69,72 @@ const getEntriesRecordByRef = (
58
69
 
59
70
  const fetchAndCacheEntries = async (
60
71
  entriesCache: EntriesCache,
72
+ contentCache: ContentCache,
61
73
  cacheSize: number,
62
74
  context: ApolloContext,
63
75
  ref: string,
64
76
  ): Promise<EntriesRecord> => {
65
- let allEntries: Entry[]
66
- try {
67
- allEntries = await context.gitAdapter.getEntries(ref)
68
- } catch (err) {
69
- if (err instanceof GitAdapterError) {
70
- throw createError(err.message, err.code, {})
77
+ const entryHashes = await callGitAdapter(() =>
78
+ context.gitAdapter.getEntryHashes(ref),
79
+ )
80
+
81
+ // hold on to known content now, as it may be evicted from the content cache while missing content is fetched
82
+ const contentByHash = new Map<ContentHash, EntryContent>()
83
+ const idsToFetchByHash = new Map<ContentHash, string>()
84
+ for (const { id, hash } of entryHashes) {
85
+ const content = contentCache.get(hash)
86
+ if (content !== undefined) {
87
+ contentByHash.set(hash, content)
88
+ } else if (!idsToFetchByHash.has(hash)) {
89
+ // entries with equal hash have equal content, so fetching one of them is sufficient
90
+ idsToFetchByHash.set(hash, id)
91
+ }
92
+ }
93
+
94
+ if (idsToFetchByHash.size > 0) {
95
+ const fetchedEntries = await callGitAdapter(() =>
96
+ context.gitAdapter.getEntriesByIds(ref, [...idsToFetchByHash.values()]),
97
+ )
98
+ const fetchedEntriesById = new Map(
99
+ fetchedEntries.map((entry) => [entry.id, entry]),
100
+ )
101
+ for (const [hash, id] of idsToFetchByHash) {
102
+ const fetchedEntry = fetchedEntriesById.get(id)
103
+ if (fetchedEntry === undefined) {
104
+ throw createError(
105
+ `Git adapter did not return requested entry "${id}".`,
106
+ ErrorCode.INTERNAL_ERROR,
107
+ {},
108
+ )
109
+ }
110
+ contentByHash.set(hash, createEntryContent(fetchedEntry))
71
111
  }
72
- const message = err instanceof Error ? err.message : String(err)
73
- throw createError(message, ErrorCode.INTERNAL_ERROR, {})
74
112
  }
75
113
 
76
- const entriesById = new Map(allEntries.map((entry) => [entry.id, entry]))
114
+ const entriesById = new Map<string, Entry>()
77
115
  const entriesByType = new Map<string, Entry[]>()
78
- for (const entry of allEntries) {
116
+ for (const { id, hash } of entryHashes) {
117
+ const entry: Entry = {
118
+ id: id,
119
+ ...(contentByHash.get(hash) as EntryContent),
120
+ }
121
+ entriesById.set(id, entry)
79
122
  const existingEntriesOfType = entriesByType.get(entry.metadata.type) || []
80
123
  existingEntriesOfType.push(entry)
81
124
  entriesByType.set(entry.metadata.type, existingEntriesOfType)
82
125
  }
83
126
 
84
- const newCacheRecord = {
85
- byType: entriesByType,
86
- byId: entriesById,
127
+ const newCacheRecord: CommitCacheRecord = {
128
+ entriesRecord: {
129
+ byType: entriesByType,
130
+ byId: entriesById,
131
+ },
132
+ contentHashes: [...contentByHash.keys()],
87
133
  }
88
134
 
135
+ for (const [hash, content] of contentByHash) {
136
+ contentCache.set(hash, content)
137
+ }
89
138
  entriesCache.set(ref, newCacheRecord)
90
139
 
91
140
  if (entriesCache.size > cacheSize) {
@@ -93,10 +142,48 @@ const fetchAndCacheEntries = async (
93
142
  const oldestKey = entriesCache.keys().next().value as Ref | undefined
94
143
  if (oldestKey !== undefined) {
95
144
  entriesCache.delete(oldestKey)
145
+ removeUnreferencedContent(entriesCache, contentCache)
96
146
  }
97
147
  }
98
148
 
99
- return newCacheRecord
149
+ return newCacheRecord.entriesRecord
150
+ }
151
+
152
+ const createEntryContent = (entry: Entry): EntryContent => {
153
+ const content: EntryContent = { metadata: entry.metadata }
154
+ if (entry.data !== undefined) {
155
+ content.data = entry.data
156
+ }
157
+ return content
158
+ }
159
+
160
+ const removeUnreferencedContent = (
161
+ entriesCache: EntriesCache,
162
+ contentCache: ContentCache,
163
+ ): void => {
164
+ const referencedHashes = new Set<ContentHash>()
165
+ for (const cacheRecord of entriesCache.values()) {
166
+ for (const hash of cacheRecord.contentHashes) {
167
+ referencedHashes.add(hash)
168
+ }
169
+ }
170
+ for (const hash of contentCache.keys()) {
171
+ if (!referencedHashes.has(hash)) {
172
+ contentCache.delete(hash)
173
+ }
174
+ }
175
+ }
176
+
177
+ const callGitAdapter = async <T>(operation: () => Promise<T>): Promise<T> => {
178
+ try {
179
+ return await operation()
180
+ } catch (err) {
181
+ if (err instanceof GitAdapterError) {
182
+ throw createError(err.message, err.code, {})
183
+ }
184
+ const message = err instanceof Error ? err.message : String(err)
185
+ throw createError(message, ErrorCode.INTERNAL_ERROR, {})
186
+ }
100
187
  }
101
188
 
102
189
  const getSchemaStringByRef = async (
@@ -114,16 +201,9 @@ const getSchemaStringByRef = async (
114
201
  return schemaCacheRecord
115
202
  }
116
203
 
117
- let schemaString
118
- try {
119
- schemaString = await context.gitAdapter.getSchema(ref)
120
- } catch (err) {
121
- if (err instanceof GitAdapterError) {
122
- throw createError(err.message, err.code, {})
123
- }
124
- const message = err instanceof Error ? err.message : String(err)
125
- throw createError(message, ErrorCode.INTERNAL_ERROR, {})
126
- }
204
+ const schemaString = await callGitAdapter(() =>
205
+ context.gitAdapter.getSchema(ref),
206
+ )
127
207
 
128
208
  schemaCache.set(ref, schemaString)
129
209
 
@@ -141,7 +221,8 @@ const getSchemaStringByRef = async (
141
221
  export const createCacheHandler = (
142
222
  cacheSize: number = MAX_CACHE_ENTRIES,
143
223
  ): RepositoryCacheHandler => {
144
- const entriesCache: EntriesCache = new Map<Ref, EntriesRecord>()
224
+ const entriesCache: EntriesCache = new Map<Ref, CommitCacheRecord>()
225
+ const contentCache: ContentCache = new Map<ContentHash, EntryContent>()
145
226
  const schemaCache: SchemaCache = new Map<Ref, string>()
146
227
  const inflightEntries: InflightEntries = new Map<
147
228
  Ref,
@@ -149,7 +230,13 @@ export const createCacheHandler = (
149
230
  >()
150
231
  return {
151
232
  getEntriesRecord: (...args) =>
152
- getEntriesRecordByRef(entriesCache, inflightEntries, cacheSize, ...args),
233
+ getEntriesRecordByRef(
234
+ entriesCache,
235
+ contentCache,
236
+ inflightEntries,
237
+ cacheSize,
238
+ ...args,
239
+ ),
153
240
  getSchema: (...args) =>
154
241
  getSchemaStringByRef(schemaCache, cacheSize, ...args),
155
242
  }