Improved atomicity

This commit is contained in:
didier amyot committed 2023-06-13 12:24:57 -04:00
1 parent b70628264e
commit b8b3e348e8
3 files changed
+48 -15

No files matched your search

+19 -7
View File
@@ -14,6 +14,7 @@ interface SerializedFile {
path: string;
contentSize: number;
compression: CompressionAlgorithm;
creationTime: number;
}
interface SerializedFilePathIndex {
@@ -43,8 +44,11 @@ export class DenoKVBlobService implements BlobService {
}
const blob_id = await this.sha1(content);
await this.kv.set(['blob_index', blobIndex, chunckIndex], blob_id);
await this.kv.set(['blob', blob_id], content);
await this.kv.atomic()
.check({key: ['blob_index', blobIndex, chunckIndex], versionstamp: null })
.set(['blob_index', blobIndex, chunckIndex], blob_id)
.set(['blob', blob_id], content)
.commit();
}
persistBlob(index: string, content: Uint8Array): Promise<number> {
@@ -107,12 +111,12 @@ export class DenoKVFileService implements FileService {
createFromFullContent(
path: string,
content: string | Uint8Array,
): Promise<FileMetaData> {
): Promise<FileMetaData | null> {
const reader = content instanceof Uint8Array ? new Buffer(content) : new StringReader(content);
return this.createFromReader(path, reader);
}
async createFromReader(path: string, content: Deno.Reader): Promise<FileMetaData> {
async createFromReader(path: string, content: Deno.Reader): Promise<FileMetaData | null> {
const newId = crypto.randomUUID();
const compressedContent = readableStreamFromReader(content).pipeThrough(new CompressionStream(CompressionAlgorithm.GZIP))
@@ -123,12 +127,18 @@ export class DenoKVFileService implements FileService {
path,
contentSize: size,
compression: CompressionAlgorithm.GZIP,
creationTime: Date.now()
};
const idx: SerializedFilePathIndex = { fileId: newId };
await this.kv.set(['file', newId], serializedFile);
await this.kv.set(['file_index_path', path], idx);
return { id: newId, path, contentSize: size };
const ret = await this.kv.atomic()
.check({key: ['file_index_path', path], versionstamp: null })
.set(['file', newId], serializedFile)
.set(['file_index_path', path], idx)
.commit();
return ret.ok ? { id: newId, path, contentSize: size } : null;
}
async *list(): AsyncIterable<FileMetaData> {
@@ -253,10 +263,12 @@ export class DenoKVFileService implements FileService {
id: fileObject.value.id,
contentSize: fileObject.value.contentSize,
compression: fileObject.value.compression,
creationTime: fileObject.value.creationTime,
};
await this.kv.atomic()
.check(fileObject)
.check(idx)
.check({key: ['file_index_path', newPath], versionstamp: null })
.delete(idx.key)
.set(['file_index_path', newPath], idx.value)
.set(fileObject.key, newFile)
+2 -2
View File
@@ -10,9 +10,9 @@ export interface FileService {
createFromFullContent(
path: string,
content: string | Uint8Array,
): Promise<FileMetaData>;
): Promise<FileMetaData | null>;
createFromReader(path: string, content: Deno.Reader): Promise<FileMetaData>;
createFromReader(path: string, content: Deno.Reader): Promise<FileMetaData | null>;
getRawContentByPath(path: string): Promise<Uint8Array | null>;