-
Notifications
You must be signed in to change notification settings - Fork 1
Add bucket initialization to SourceService operations #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,13 +48,34 @@ export interface SourceCreateInput { | |
| * Service for managing sources and raw payload storage. | ||
| */ | ||
| export class SourceService { | ||
| private bucketReady: Promise<void> | null = null; | ||
|
|
||
| constructor( | ||
| private db: DrizzleDB, | ||
| private minioClient: MinioClient, | ||
| private bucket: string, | ||
| private inlineThreshold = 1024, // bytes | ||
| ) {} | ||
|
|
||
| /** Ensure the S3/MinIO bucket exists, creating it if necessary */ | ||
| private ensureBucket(): Promise<void> { | ||
| if (!this.bucketReady) { | ||
| this.bucketReady = this.minioClient | ||
| .bucketExists(this.bucket) | ||
| .then((exists) => { | ||
| if (!exists) { | ||
| return this.minioClient.makeBucket(this.bucket); | ||
| } | ||
| }) | ||
| .catch((err) => { | ||
| // Reset so next call retries | ||
| this.bucketReady = null; | ||
| throw err; | ||
| }); | ||
| } | ||
| return this.bucketReady; | ||
| } | ||
|
|
||
| /** Insert multiple sources with optional inline or blob payloads */ | ||
| async insertMany(inputs: SourceCreateInput[]): Promise<{ | ||
| successes: TypeId<"source">[]; | ||
|
|
@@ -98,6 +119,7 @@ export class SourceService { | |
| .returning(); | ||
|
|
||
| // 2. Handle payloads | ||
| await this.ensureBucket(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For a minor optimization, you could defer calling |
||
| for (const row of inserted) { | ||
| const lookupKey = makeLookupKey(row.userId, row.type, row.externalId); | ||
| const input = inputLookup.get(lookupKey); | ||
|
|
@@ -177,6 +199,7 @@ export class SourceService { | |
|
|
||
| /** Hard delete a source: remove blob then drop the DB row */ | ||
| async deleteHard(userId: string, sourceId: TypeId<"source">): Promise<void> { | ||
| await this.ensureBucket(); | ||
| const key = `${userId}/${sourceId}`; | ||
| // delete blob, ignore errors | ||
| try { | ||
|
|
@@ -203,6 +226,7 @@ export class SourceService { | |
| and(eq(src.userId, userId), inArray(src.id, sourceIds)), | ||
| }); | ||
| const results: RawResult[] = []; | ||
| await this.ensureBucket(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For a minor optimization, you could defer calling |
||
|
|
||
| for (const row of rows) { | ||
| const meta = metadataSchema.parse(row.metadata ?? {}); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the current promise-based implementation is correct, using
async/awaitcan improve readability and make the logic easier to follow. This is more idiomatic in modern TypeScript/JavaScript. TheasyncIIFE (Immediately Invoked Function Expression) pattern ensures the promise is created and assigned synchronously, preserving the lazy-initialization and race-condition-free behavior of your original implementation.