distribute upload chunks across multiple servers

This commit is contained in:
shum
2026-02-18 14:17:03 +00:00
parent eaa81dcc5d
commit ca2781a485
2 changed files with 8 additions and 6 deletions
+6 -3
View File
@@ -105,10 +105,11 @@ export interface UploadOptions {
export async function uploadFile(
agent: XFTPClientAgent,
server: XFTPServer,
servers: XFTPServer[],
encrypted: EncryptedFileMetadata,
options?: UploadOptions
): Promise<UploadResult> {
if (servers.length === 0) throw new Error("uploadFile: servers list is empty")
const {onProgress, redirectThreshold, readChunk: readChunkOpt} = options ?? {}
const readChunk: (offset: number, size: number) => Promise<Uint8Array> = readChunkOpt
? readChunkOpt
@@ -122,6 +123,7 @@ export async function uploadFile(
for (let i = 0; i < specs.length; i++) {
const spec = specs[i]
const chunkNo = i + 1
const server = servers[Math.floor(Math.random() * servers.length)]
const sndKp = generateEd25519KeyPair()
const rcvKp = generateEd25519KeyPair()
const chunkData = await readChunk(spec.chunkOffset, spec.chunkSize)
@@ -151,7 +153,7 @@ export async function uploadFile(
let finalRcvDescription = rcvDescription
const threshold = redirectThreshold ?? DEFAULT_REDIRECT_THRESHOLD
if (uri.length > threshold && sentChunks.length > 1) {
finalRcvDescription = await uploadRedirectDescription(agent, server, rcvDescription)
finalRcvDescription = await uploadRedirectDescription(agent, servers, rcvDescription)
uri = encodeDescriptionURI(finalRcvDescription)
}
return {rcvDescription: finalRcvDescription, sndDescription, uri}
@@ -186,7 +188,7 @@ function buildDescription(
async function uploadRedirectDescription(
agent: XFTPClientAgent,
server: XFTPServer,
servers: XFTPServer[],
innerFd: FileDescription
): Promise<FileDescription> {
const yaml = encodeFileDescription(innerFd)
@@ -197,6 +199,7 @@ async function uploadRedirectDescription(
for (let i = 0; i < specs.length; i++) {
const spec = specs[i]
const chunkNo = i + 1
const server = servers[Math.floor(Math.random() * servers.length)]
const sndKp = generateEd25519KeyPair()
const rcvKp = generateEd25519KeyPair()
const chunkData = enc.encData.subarray(spec.chunkOffset, spec.chunkOffset + spec.chunkSize)
+2 -3
View File
@@ -1,5 +1,5 @@
import {createCryptoBackend} from './crypto-backend.js'
import {getServers, pickRandomServer} from './servers.js'
import {getServers} from './servers.js'
import {createProgressRing} from './progress.js'
import {
newXFTPAgent, closeXFTPAgent, uploadFile, encodeDescriptionURI,
@@ -131,8 +131,7 @@ export function initUpload(app: HTMLElement) {
chunkSizes: encrypted.chunkSizes
}
const servers = getServers()
const server = pickRandomServer(servers)
const result = await uploadFile(agent, server, metadata, {
const result = await uploadFile(agent, servers, metadata, {
readChunk: (off, sz) => backend.readChunk(off, sz),
onProgress: (uploaded, total) => {
ring.update(0.3 + (uploaded / total) * 0.7)