Files
speckle-server/packages/server/modules/core/utils/chunking.ts
T
Kristaps Fabians Geikins 1d2a594f0a chore: upgrade TS 5.2 -> 5.7.3 & ESLint to 9.20.1 (#4032)
* chore: upgrade TS 5.2 -> 5.7.3

* vite dts fix

* lint fix

* resolutions fix

* ui comp build fix

* precommit fix?

* latest eslint version

* autoloader fix

* undo unnecessary viewer change

* eslint fixes fe2 + trying disabled type linting

* lint fixes
2025-02-20 14:18:18 +02:00

68 lines
2.2 KiB
TypeScript

import { InsertableSpeckleObject } from '@/modules/core/domain/objects/types'
import { BaseError } from '@/modules/shared/errors'
import { Options } from 'verror'
type InsertionObject = Pick<InsertableSpeckleObject, 'data'>
export class ArgumentError extends BaseError {
static defaultMessage = 'Invalid argument value provided'
constructor(message?: string, options?: Options | Error) {
super(message, options)
}
static statusCode = 400
}
// since we're mostly using this for an artificial limit calculation
// we can live with a somewhat imprecise but fast estimate
// Js uses utf16 so the in memory string size in bytes is length * 2
// this is just the in memory string size, not the utf-8 encoded byte size
// since our data is mostly ascii characters, its prob safe to use
// string.length is a slight underestimation of the actual size
export const estimateStringByteSize = (str: string) => str.length
export const estimateStringMegabyteSize = (str: string) =>
estimateStringByteSize(str) / 1_000_000
export const chunkInsertionObjectArray = <O extends InsertionObject = InsertionObject>({
objects,
chunkSizeLimitMb,
chunkLengthLimit
}: {
chunkSizeLimitMb: number
chunkLengthLimit: number
objects: O[]
}): O[][] => {
if (chunkLengthLimit < 1)
throw new ArgumentError('Chunks must have a length limit > 1')
if (chunkSizeLimitMb <= 0)
throw new ArgumentError('Chunks must have a size in MB limit > 0')
let currentChunkSize = 0
let currentChunkLength = 0
const chunkedObjects: O[][] = []
let currentBatch: O[] = []
for (const obj of objects) {
// if limits are exceeded start a new batch
if (
currentChunkSize >= chunkSizeLimitMb ||
currentChunkLength >= chunkLengthLimit
) {
// push the current batch into the final chunks
chunkedObjects.push(currentBatch)
// reset the current batch
currentBatch = []
// reset limits
currentChunkSize = 0
currentChunkLength = 0
}
// do some proper chunking here
// insert the batch to returned chunks
currentChunkLength++
currentChunkSize += estimateStringMegabyteSize(obj.data)
currentBatch.push(obj)
}
// do not forget to push the final batch
chunkedObjects.push(currentBatch)
return chunkedObjects
}