Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.

perf: don't serialize data to IDB (#3824)

Cas_ d845f88b 046c6e5e

Changed files
+11 -52
.changeset
exchanges
graphcache
src
default-storage
+5
.changeset/orange-rabbits-poke.md
···
···
+
---
+
'@urql/exchange-graphcache': major
+
---
+
+
Don't serialize data to IDB. This invalidates all existing data, but greatly improves performance of read/write operations.
+6 -52
exchanges/graphcache/src/default-storage/index.ts
···
req.result.createObjectStore(METADATA_STORE_NAME);
};
-
const serializeEntry = (entry: string): string => entry.replace(/:/g, '%3a');
-
-
const deserializeEntry = (entry: string): string =>
-
entry.replace(/%3a/g, ':');
-
-
const serializeBatch = (): string => {
-
let data = '';
-
for (const key in batch) {
-
const value = batch[key];
-
data += serializeEntry(key);
-
data += ':';
-
if (value) data += serializeEntry(value);
-
data += ':';
-
}
-
-
return data;
-
};
-
-
const deserializeBatch = (input: string) => {
-
const data = {};
-
let char = '';
-
let key = '';
-
let entry = '';
-
let mode = 0;
-
let index = 0;
-
while (index < input.length) {
-
entry = '';
-
while ((char = input[index++]) !== ':' && char) {
-
entry += char;
-
}
-
-
if (mode) {
-
data[key] = deserializeEntry(entry) || undefined;
-
mode = 0;
-
} else {
-
key = deserializeEntry(entry);
-
mode = 1;
-
}
-
}
-
-
return data;
-
};
-
return {
clear() {
return database$.then(database => {
···
database
.transaction(ENTRIES_STORE_NAME, 'readwrite')
.objectStore(ENTRIES_STORE_NAME)
-
.put(serializeBatch(), timestamp)
);
})
.then(toUndefined, toUndefined);
},
readData(): Promise<SerializedEntries> {
-
const chunks: string[] = [];
return database$
.then(database => {
const transaction = database.transaction(
···
store.delete(key);
} else {
const request = store.get(key);
-
const index = chunks.length;
-
chunks.push('');
request.onsuccess = () => {
-
const result = '' + request.result;
-
if (key === timestamp)
-
Object.assign(batch, deserializeBatch(result));
-
chunks[index] = result;
};
}
···
return getTransactionPromise(transaction);
})
.then(
-
() => deserializeBatch(chunks.join('')),
() => batch
);
},
···
req.result.createObjectStore(METADATA_STORE_NAME);
};
return {
clear() {
return database$.then(database => {
···
database
.transaction(ENTRIES_STORE_NAME, 'readwrite')
.objectStore(ENTRIES_STORE_NAME)
+
.put(batch, timestamp)
);
})
.then(toUndefined, toUndefined);
},
readData(): Promise<SerializedEntries> {
+
const data: SerializedEntries = {};
return database$
.then(database => {
const transaction = database.transaction(
···
store.delete(key);
} else {
const request = store.get(key);
request.onsuccess = () => {
+
const result = request.result;
+
if (key === timestamp) Object.assign(batch, result);
+
Object.assign(data, result);
};
}
···
return getTransactionPromise(transaction);
})
.then(
+
() => data,
() => batch
);
},