fix(nbstore): improve blob size error handling with human-readable limit (#12027)
Closes: [BS-3332](https://linear.app/affine-design/issue/BS-3332/错误信息) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved error messages when file uploads exceed the allowed size, now showing the maximum file size limit in a human-readable format. - Enhanced status updates for oversized files by displaying clear error messages during blob uploads. - **Style** - Error messages for file size limits are now more user-friendly and informative. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -95,7 +95,7 @@ export class CloudBlobStorage extends BlobStorageBase {
|
|||||||
try {
|
try {
|
||||||
const blobSizeLimit = await this.getBlobSizeLimit();
|
const blobSizeLimit = await this.getBlobSizeLimit();
|
||||||
if (blob.data.byteLength > blobSizeLimit) {
|
if (blob.data.byteLength > blobSizeLimit) {
|
||||||
throw new OverSizeError();
|
throw new OverSizeError(this.humanReadableBlobSizeLimitCache);
|
||||||
}
|
}
|
||||||
await this.connection.gql({
|
await this.connection.gql({
|
||||||
query: setBlobMutation,
|
query: setBlobMutation,
|
||||||
@@ -113,10 +113,10 @@ export class CloudBlobStorage extends BlobStorageBase {
|
|||||||
throw new OverCapacityError();
|
throw new OverCapacityError();
|
||||||
}
|
}
|
||||||
if (userFriendlyError.is('BLOB_QUOTA_EXCEEDED')) {
|
if (userFriendlyError.is('BLOB_QUOTA_EXCEEDED')) {
|
||||||
throw new OverSizeError();
|
throw new OverSizeError(this.humanReadableBlobSizeLimitCache);
|
||||||
}
|
}
|
||||||
if (userFriendlyError.is('CONTENT_TOO_LARGE')) {
|
if (userFriendlyError.is('CONTENT_TOO_LARGE')) {
|
||||||
throw new OverSizeError();
|
throw new OverSizeError(this.humanReadableBlobSizeLimitCache);
|
||||||
}
|
}
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
@@ -148,6 +148,7 @@ export class CloudBlobStorage extends BlobStorageBase {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private humanReadableBlobSizeLimitCache: string | null = null;
|
||||||
private blobSizeLimitCache: number | null = null;
|
private blobSizeLimitCache: number | null = null;
|
||||||
private blobSizeLimitCacheTime = 0;
|
private blobSizeLimitCacheTime = 0;
|
||||||
private async getBlobSizeLimit() {
|
private async getBlobSizeLimit() {
|
||||||
@@ -164,6 +165,8 @@ export class CloudBlobStorage extends BlobStorageBase {
|
|||||||
variables: { id: this.options.id },
|
variables: { id: this.options.id },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.humanReadableBlobSizeLimitCache =
|
||||||
|
res.workspace.quota.humanReadable.blobLimit;
|
||||||
this.blobSizeLimitCache = res.workspace.quota.blobLimit;
|
this.blobSizeLimitCache = res.workspace.quota.blobLimit;
|
||||||
this.blobSizeLimitCacheTime = Date.now();
|
this.blobSizeLimitCacheTime = Date.now();
|
||||||
return this.blobSizeLimitCache;
|
return this.blobSizeLimitCache;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export class HttpConnection extends DummyConnection {
|
|||||||
|
|
||||||
const timeout = 15000;
|
const timeout = 15000;
|
||||||
const timeoutId = setTimeout(() => {
|
const timeoutId = setTimeout(() => {
|
||||||
abortController.abort('timeout');
|
abortController.abort(new Error('request timeout'));
|
||||||
}, timeout);
|
}, timeout);
|
||||||
|
|
||||||
const res = await globalThis
|
const res = await globalThis
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export class OverSizeError extends Error {
|
export class OverSizeError extends Error {
|
||||||
constructor(public originError?: any) {
|
constructor(limit: string | null) {
|
||||||
super('Blob size exceeds the limit.');
|
const formattedLimit = limit ? `${limit} ` : '';
|
||||||
|
super(`File size exceeds the ${formattedLimit}limit.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,8 +185,7 @@ export class BlobSyncPeer {
|
|||||||
this.status.remoteOverCapacity();
|
this.status.remoteOverCapacity();
|
||||||
this.status.blobError(blob.key, 'Remote storage over capacity');
|
this.status.blobError(blob.key, 'Remote storage over capacity');
|
||||||
} else if (err instanceof OverSizeError) {
|
} else if (err instanceof OverSizeError) {
|
||||||
this.status.blobOverSize(blob.key);
|
this.status.blobOverSizeWithError(blob.key, err.message);
|
||||||
this.status.blobError(blob.key, 'Blob size too large');
|
|
||||||
} else {
|
} else {
|
||||||
this.status.blobError(
|
this.status.blobError(
|
||||||
blob.key,
|
blob.key,
|
||||||
@@ -445,7 +444,6 @@ class BlobSyncPeerStatus {
|
|||||||
if (deleted) {
|
if (deleted) {
|
||||||
this.statusUpdatedSubject$.next(blobId);
|
this.statusUpdatedSubject$.next(blobId);
|
||||||
}
|
}
|
||||||
this.blobErrorFree(blobId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blobWillUpload(blobId: string) {
|
blobWillUpload(blobId: string) {
|
||||||
@@ -517,6 +515,12 @@ class BlobSyncPeerStatus {
|
|||||||
this.statusUpdatedSubject$.next(blobId);
|
this.statusUpdatedSubject$.next(blobId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blobOverSizeWithError(blobId: string, errorMessage: string) {
|
||||||
|
this.overSize.add(blobId);
|
||||||
|
this.error.set(blobId, errorMessage);
|
||||||
|
this.statusUpdatedSubject$.next(blobId);
|
||||||
|
}
|
||||||
|
|
||||||
blobErrorFree(blobId: string) {
|
blobErrorFree(blobId: string) {
|
||||||
let deleted = false;
|
let deleted = false;
|
||||||
deleted = this.error.delete(blobId) || deleted;
|
deleted = this.error.delete(blobId) || deleted;
|
||||||
|
|||||||
Reference in New Issue
Block a user