Skip to content

Commit c3960be

Browse files
committed
improvement(db): finish workspace file size cutover
1 parent d86fdc1 commit c3960be

27 files changed

Lines changed: 20395 additions & 90 deletions

apps/sim/app/api/files/uploads/finalizers.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
registerUploadedWorkspaceFile,
1515
type WorkspaceFileRecord,
1616
} from '@/lib/uploads/contexts/workspace'
17-
import { type StorageContext, toLegacyWorkspaceFileSize } from '@/lib/uploads/shared/types'
17+
import { getWorkspaceFileSize, type StorageContext } from '@/lib/uploads/shared/types'
1818
import { UploadSessionError, type UploadSessionRecord } from '@/lib/uploads/upload-session/service'
1919
import { toV2File } from '@/app/api/v2/files/utils'
2020

@@ -364,7 +364,6 @@ async function insertOrLoadFileMetadata(
364364
originalName: input.originalName,
365365
displayName: input.originalName,
366366
contentType: input.contentType,
367-
size: toLegacyWorkspaceFileSize(input.size),
368367
sizeBytes: input.size,
369368
deletedAt: null,
370369
uploadedAt: now,
@@ -396,7 +395,7 @@ async function findFileMetadataByKey(key: string): Promise<FileMetadataRecord |
396395
}
397396

398397
function assertMatchingMetadata(existing: FileMetadataRecord, input: FinalizedMetadataInput): void {
399-
const existingSize = existing.sizeBytes ?? existing.size
398+
const existingSize = getWorkspaceFileSize(existing)
400399
if (
401400
existing.key !== input.key ||
402401
existing.userId !== input.userId ||

apps/sim/app/api/mothership/local-files/stage/route.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ vi.mock('@sim/db/schema', () => ({
3939
displayName: 'workspaceFiles.displayName',
4040
originalName: 'workspaceFiles.originalName',
4141
contentType: 'workspaceFiles.contentType',
42-
size: 'workspaceFiles.size',
42+
sizeBytes: 'workspaceFiles.sizeBytes',
4343
deletedAt: 'workspaceFiles.deletedAt',
4444
},
4545
}))
@@ -95,7 +95,7 @@ describe('POST /api/mothership/local-files/stage', () => {
9595
displayName: null,
9696
originalName: 'report.pdf',
9797
contentType: 'application/pdf',
98-
size: 42,
98+
sizeBytes: 42,
9999
},
100100
])
101101
mockWhere.mockReturnValue({ limit: mockLimit })
@@ -139,7 +139,7 @@ describe('POST /api/mothership/local-files/stage', () => {
139139
displayName: 'report (2).pdf',
140140
originalName: 'report.pdf',
141141
contentType: 'application/pdf',
142-
size: 42,
142+
sizeBytes: 42,
143143
},
144144
])
145145
const response = await POST(request())

apps/sim/app/api/mothership/local-files/stage/route.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
trackChatUpload,
1818
WorkspaceFileKeyOwnershipError,
1919
} from '@/lib/uploads/contexts/workspace/workspace-file-manager'
20+
import { getWorkspaceFileSize } from '@/lib/uploads/shared/types'
2021
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
2122

2223
const logger = createLogger('StageLocalFileUploadAPI')
@@ -52,7 +53,7 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
5253
displayName: workspaceFiles.displayName,
5354
originalName: workspaceFiles.originalName,
5455
contentType: workspaceFiles.contentType,
55-
size: workspaceFiles.size,
56+
sizeBytes: workspaceFiles.sizeBytes,
5657
})
5758
.from(workspaceFiles)
5859
.where(
@@ -87,7 +88,7 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
8788
key,
8889
file.originalName,
8990
file.contentType,
90-
file.size
91+
getWorkspaceFileSize(file)
9192
)
9293
).displayName
9394

apps/sim/background/cleanup-soft-deletes.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,7 @@ async function selectExpiredWorkspaceFiles(
113113
key: workspaceFiles.key,
114114
workspaceId: workspaceFiles.workspaceId,
115115
context: workspaceFiles.context,
116-
size: sql<number>`coalesce(${workspaceFiles.sizeBytes}, ${workspaceFiles.size})`.mapWith(
117-
Number
118-
),
116+
size: sql<number>`${workspaceFiles.sizeBytes}`.mapWith(Number),
119117
})
120118
.from(workspaceFiles)
121119
.where(
@@ -329,9 +327,7 @@ async function deleteExpiredBillableWorkspaceFileRows(
329327
)
330328
.returning({
331329
id: workspaceFiles.id,
332-
size: sql<number>`coalesce(${workspaceFiles.sizeBytes}, ${workspaceFiles.size})`.mapWith(
333-
Number
334-
),
330+
size: sql<number>`${workspaceFiles.sizeBytes}`.mapWith(Number),
335331
})
336332
if (deletedRows.some(({ size }) => size < 0)) {
337333
throw new Error('Cannot delete workspace files with negative stored-byte metadata')

apps/sim/ee/workspace-forking/lib/copy/copy-files.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ describe('planForkFileCopies', () => {
549549
displayName: null,
550550
contentType: 'text/plain',
551551
size: 4321,
552+
sizeBytes: 4321,
552553
deletedAt: null,
553554
uploadedAt: new Date('2026-01-01'),
554555
updatedAt: new Date('2026-01-01'),
@@ -593,6 +594,7 @@ describe('planForkFileCopies', () => {
593594
displayName: null,
594595
contentType: 'text/plain',
595596
size: 4321,
597+
sizeBytes: 4321,
596598
deletedAt: null,
597599
uploadedAt: new Date('2026-01-01'),
598600
updatedAt: new Date('2026-01-01'),

apps/sim/ee/workspace-forking/lib/copy/copy-files.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
headObject,
2121
uploadFile,
2222
} from '@/lib/uploads/core/storage-service'
23-
import type { StorageContext } from '@/lib/uploads/shared/types'
23+
import { getWorkspaceFileSize, type StorageContext } from '@/lib/uploads/shared/types'
2424
import { MAX_FILE_SIZE } from '@/lib/uploads/utils/validation'
2525
import { resolveForkFolderMapping } from '@/ee/workspace-forking/lib/copy/copy-workflows'
2626
import {
@@ -219,7 +219,7 @@ export async function planForkFileCopies(params: {
219219
context: meta.context as StorageContext,
220220
fileName: meta.originalName,
221221
contentType: meta.contentType,
222-
size: meta.size,
222+
size: getWorkspaceFileSize(meta),
223223
targetFileId: childFileId,
224224
displayName: meta.displayName,
225225
userId,
@@ -341,7 +341,7 @@ export async function executeForkFileBlobCopies(
341341
originalName: targetOriginalName,
342342
displayName: targetDisplayName,
343343
contentType: task.contentType,
344-
size: task.size,
344+
sizeBytes: task.size,
345345
deletedAt: null,
346346
uploadedAt: new Date(),
347347
})
@@ -389,7 +389,7 @@ export async function executeForkFileBlobCopies(
389389
originalName: targetOriginalName,
390390
displayName: targetDisplayName,
391391
contentType: task.contentType,
392-
size: task.size,
392+
sizeBytes: task.size,
393393
deletedAt: null,
394394
uploadedAt: new Date(),
395395
})

apps/sim/ee/workspace-forking/lib/copy/storage-quota.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export interface ForkCopyBytesSelection {
2525
/**
2626
* Byte total a fork/sync copy selection would duplicate into the target: selected
2727
* workspace-file blobs plus the selected knowledge bases' stored document blobs. Sizes
28-
* come from the metadata rows (`workspace_files.size`, `document.file_size`) - no blob
28+
* come from the metadata rows (`workspace_files.size_bytes`, `document.file_size`) - no blob
2929
* reads. Both sums scope to the source workspace with the same filters the copy itself
3030
* applies, so an id that is not actually copyable can only over-count (block), never
3131
* under-count.
@@ -48,7 +48,7 @@ export async function sumForkCopyBytes(
4848
fileSelectors.length === 0
4949
? sql<number>`0`
5050
: sql<number>`(
51-
SELECT coalesce(sum(coalesce(${workspaceFiles.sizeBytes}, ${workspaceFiles.size})), 0)
51+
SELECT coalesce(sum(${workspaceFiles.sizeBytes}), 0)
5252
FROM ${workspaceFiles}
5353
WHERE ${and(
5454
fileSelectors.length === 1 ? fileSelectors[0] : or(...fileSelectors),

apps/sim/lib/billing/storage/payer-transfer.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ vi.mock('@sim/db/schema', () => ({
5252
__table: 'workspaceFiles',
5353
context: 'workspaceFiles.context',
5454
deletedAt: 'workspaceFiles.deletedAt',
55-
size: 'workspaceFiles.size',
55+
sizeBytes: 'workspaceFiles.sizeBytes',
5656
workspaceId: 'workspaceFiles.workspaceId',
5757
},
5858
}))

apps/sim/lib/billing/storage/payer-transfer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ async function getExactWorkspaceStorageBytes(tx: DbOrTx, workspaceId: string): P
8282
const [row] = await tx.execute<ExactWorkspaceStorageRow>(sql`
8383
SELECT
8484
COALESCE((
85-
SELECT SUM(coalesce(${workspaceFiles.sizeBytes}, ${workspaceFiles.size}::bigint))
85+
SELECT SUM(${workspaceFiles.sizeBytes})
8686
FROM ${workspaceFiles}
8787
WHERE ${workspaceFiles.workspaceId} = ${workspaceId}
8888
AND ${workspaceFiles.context} = 'workspace'
@@ -171,7 +171,7 @@ async function getExactWorkspaceStorageBytesBatch(
171171
FROM (
172172
SELECT
173173
${workspaceFiles.workspaceId} AS workspace_id,
174-
SUM(coalesce(${workspaceFiles.sizeBytes}, ${workspaceFiles.size}::bigint)) AS workspace_file_bytes,
174+
SUM(${workspaceFiles.sizeBytes}) AS workspace_file_bytes,
175175
0::bigint AS document_bytes
176176
FROM ${workspaceFiles}
177177
WHERE ${inArray(workspaceFiles.workspaceId, workspaceIds)}

apps/sim/lib/copilot/chat/fork-chat-files.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ function makeRow(overrides: Partial<ForkableChatFileRow> = {}): ForkableChatFile
5151
displayName: 'cat.png',
5252
contentType: 'image/png',
5353
size: 100,
54+
sizeBytes: 100,
5455
deletedAt: null,
5556
uploadedAt: new Date('2026-06-01T00:00:00.000Z'),
5657
updatedAt: new Date('2026-06-01T00:00:00.000Z'),

0 commit comments

Comments
 (0)