-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(doc-storage): impl blob storages
- Loading branch information
Showing
9 changed files
with
448 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { type Blob, BlobStorage, type ListedBlob } from '../../storage'; | ||
import { type SpaceIDB, SpaceIndexedDbManager } from './db'; | ||
|
||
export class IndexedDBBlobStorage extends BlobStorage { | ||
private db!: SpaceIDB; | ||
|
||
override async connect(): Promise<void> { | ||
this.db = await SpaceIndexedDbManager.open( | ||
`${this.spaceType}:${this.spaceId}` | ||
); | ||
} | ||
|
||
override async getBlob(key: string): Promise<Blob | null> { | ||
const trx = this.db.transaction('blobs', 'readonly'); | ||
const blob = await trx.store.get(key); | ||
|
||
if (!blob || blob.deletedAt) { | ||
return null; | ||
} | ||
|
||
return blob; | ||
} | ||
|
||
override async setBlob(blob: Blob): Promise<void> { | ||
const trx = this.db.transaction('blobs', 'readwrite'); | ||
await trx.store.put({ | ||
...blob, | ||
size: blob.data.length, | ||
createdAt: new Date(), | ||
deletedAt: null, | ||
}); | ||
} | ||
|
||
override async deleteBlob(key: string, permanently = false): Promise<void> { | ||
const trx = this.db.transaction('blobs', 'readwrite'); | ||
if (permanently) { | ||
await trx.store.delete(key); | ||
} else { | ||
const blob = await trx.store.get(key); | ||
if (blob) { | ||
await trx.store.put({ | ||
...blob, | ||
deletedAt: new Date(), | ||
}); | ||
} | ||
} | ||
} | ||
|
||
override async releaseBlobs(): Promise<void> { | ||
const trx = this.db.transaction('blobs', 'readwrite'); | ||
|
||
const it = trx.store.iterate(); | ||
|
||
for await (const item of it) { | ||
if (item.value.deletedAt) { | ||
await item.delete(); | ||
} | ||
} | ||
} | ||
|
||
override async listBlobs(): Promise<ListedBlob[]> { | ||
const trx = this.db.transaction('blobs', 'readonly'); | ||
const it = trx.store.iterate(); | ||
|
||
const blobs: ListedBlob[] = []; | ||
for await (const item of it) { | ||
if (!item.value.deletedAt) { | ||
blobs.push({ key: item.value.key, size: item.value.size }); | ||
} | ||
} | ||
|
||
return blobs; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import type { DocStorage as NativeDocStorage } from '@affine/native'; | ||
|
||
import { | ||
type Blob, | ||
BlobStorage, | ||
type BlobStorageOptions, | ||
type ListedBlob, | ||
} from '../../storage'; | ||
|
||
interface SqliteBlobStorageOptions extends BlobStorageOptions { | ||
db: NativeDocStorage; | ||
} | ||
|
||
export class SqliteBlobStorage extends BlobStorage<SqliteBlobStorageOptions> { | ||
get db() { | ||
return this.options.db; | ||
} | ||
|
||
override getBlob(key: string): Promise<Blob | null> { | ||
return this.db.getBlob(key); | ||
} | ||
override setBlob(blob: Blob): Promise<void> { | ||
return this.db.setBlob({ | ||
...blob, | ||
data: Buffer.from(blob.data), | ||
}); | ||
} | ||
override deleteBlob(key: string, permanently: boolean): Promise<void> { | ||
return this.db.deleteBlob(key, permanently); | ||
} | ||
override releaseBlobs(): Promise<void> { | ||
return this.db.releaseBlobs(); | ||
} | ||
override listBlobs(): Promise<ListedBlob[]> { | ||
return this.db.listBlobs(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { Connection } from './connection'; | ||
|
||
export interface BlobStorageOptions { | ||
spaceType: string; | ||
spaceId: string; | ||
} | ||
|
||
export interface Blob { | ||
key: string; | ||
data: Uint8Array; | ||
mime: string; | ||
} | ||
|
||
export interface ListedBlob { | ||
key: string; | ||
size: number; | ||
} | ||
|
||
export abstract class BlobStorage< | ||
Options extends BlobStorageOptions = BlobStorageOptions, | ||
> extends Connection { | ||
public readonly options: Options; | ||
|
||
constructor(opts: Options) { | ||
super(); | ||
this.options = opts; | ||
} | ||
|
||
get spaceType() { | ||
return this.options.spaceType; | ||
} | ||
|
||
get spaceId() { | ||
return this.options.spaceId; | ||
} | ||
|
||
abstract getBlob(key: string): Promise<Blob | null>; | ||
abstract setBlob(blob: Blob): Promise<void>; | ||
abstract deleteBlob(key: string, permanently: boolean): Promise<void>; | ||
abstract releaseBlobs(): Promise<void>; | ||
abstract listBlobs(/* pagination? */): Promise<ListedBlob[]>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from './blob'; | ||
export * from './doc'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.