From 6fcfb67af207755ef3273df57d0275cb60a5918c Mon Sep 17 00:00:00 2001 From: zarzet Date: Sun, 26 Jul 2026 22:14:58 +0700 Subject: [PATCH] perf(go): cut redundant signed-session writes, progress-callback churn, tombstone growth --- go_backend/extension_runtime_file.go | 12 +++++-- go_backend/extension_signed_session.go | 44 ++++++++++++++++---------- go_backend/progress.go | 26 +++++++++++++++ 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/go_backend/extension_runtime_file.go b/go_backend/extension_runtime_file.go index baf556f3..2efb1f57 100644 --- a/go_backend/extension_runtime_file.go +++ b/go_backend/extension_runtime_file.go @@ -292,6 +292,7 @@ func (r *extensionRuntime) fileDownload(call goja.FunctionCall) goja.Value { } var written int64 + var lastProgressNotify int64 buf := make([]byte, 32*1024) // copyBody streams resp into progressWriter. fatal is a terminal JS error @@ -321,7 +322,11 @@ func (r *extensionRuntime) fileDownload(call goja.FunctionCall) goja.Value { return r.jsError("short write"), nil } - if onProgress != nil && contentLength > 0 { + // Throttle the JS callback like the native progress writer: + // per-read invocation is interpreter work inside the copy loop. + if onProgress != nil && contentLength > 0 && + (written-lastProgressNotify >= progressUpdateThreshold || written >= contentLength) { + lastProgressNotify = written _, _ = onProgress(goja.Undefined(), r.vm.ToValue(written), r.vm.ToValue(contentLength)) } } @@ -535,6 +540,7 @@ func (r *extensionRuntime) fileDownloadChunked(client *http.Client, urlStr, full } var totalWritten int64 + var lastProgressNotify int64 buf := make([]byte, 32*1024) maxRetries := 3 @@ -616,7 +622,9 @@ func (r *extensionRuntime) fileDownloadChunked(client *http.Client, urlStr, full return r.jsError("short write") } - if onProgress != nil && totalSize > 0 { + if onProgress != nil && totalSize > 0 && + (totalWritten-lastProgressNotify >= progressUpdateThreshold || totalWritten >= totalSize) { + lastProgressNotify = totalWritten _, _ = onProgress(goja.Undefined(), r.vm.ToValue(totalWritten), r.vm.ToValue(totalSize)) } } diff --git a/go_backend/extension_signed_session.go b/go_backend/extension_signed_session.go index 57b329c1..c2b8fe7f 100644 --- a/go_backend/extension_signed_session.go +++ b/go_backend/extension_signed_session.go @@ -95,9 +95,6 @@ func (r *extensionRuntime) signedSessionFilePath(config SignedSessionConfig) (st baseDir = r.dataDir } dir := filepath.Join(baseDir, "signed_sessions") - if err := os.MkdirAll(dir, 0700); err != nil { - return "", err - } scope := strings.Join([]string{ namespace, strings.TrimSpace(strings.ToLower(config.BaseURL)), @@ -128,32 +125,41 @@ func (r *extensionRuntime) loadSignedSession(config SignedSessionConfig) (*signe if data, err := os.ReadFile(path); err == nil { _ = json.Unmarshal(data, record) } + changed := false if strings.TrimSpace(record.InstallID) == "" { record.InstallID = randomHex(16) + changed = true } - normalizeSignedSessionRecordScope(config, record) - if err := r.saveSignedSession(config, record); err != nil { - return nil, err + if normalizeSignedSessionRecordScope(config, record) { + changed = true + } + // Only rewrite the file when the record actually changed; loads happen on + // every signed request and preflight. + if changed { + if err := r.saveSignedSession(config, record); err != nil { + return nil, err + } } return record, nil } -func normalizeSignedSessionRecordScope(config SignedSessionConfig, record *signedSessionRecord) { +// normalizeSignedSessionRecordScope stamps the config scope onto the record, +// resetting the session when the scope changed. Returns whether the record +// was modified. +func normalizeSignedSessionRecordScope(config SignedSessionConfig, record *signedSessionRecord) bool { namespace := sanitizeSignedSessionNamespace(config.Namespace) baseURL := strings.TrimSpace(config.BaseURL) appVersion := strings.TrimSpace(config.AppVersion) platform := strings.TrimSpace(config.Platform) - if record.Namespace == "" && record.BaseURL == "" && record.AppVersion == "" && record.Platform == "" { - record.Namespace = namespace - record.BaseURL = baseURL - record.AppVersion = appVersion - record.Platform = platform - return + if record.Namespace == namespace && + record.BaseURL == baseURL && + record.AppVersion == appVersion && + record.Platform == platform { + return false } - if record.Namespace != namespace || - record.BaseURL != baseURL || - record.AppVersion != appVersion || - record.Platform != platform { + blankScope := record.Namespace == "" && record.BaseURL == "" && + record.AppVersion == "" && record.Platform == "" + if !blankScope { record.SessionID = "" record.SessionSecret = "" record.ExpiresAt = "" @@ -162,6 +168,7 @@ func normalizeSignedSessionRecordScope(config SignedSessionConfig, record *signe record.BaseURL = baseURL record.AppVersion = appVersion record.Platform = platform + return true } func (r *extensionRuntime) saveSignedSession(config SignedSessionConfig, record *signedSessionRecord) error { @@ -169,6 +176,9 @@ func (r *extensionRuntime) saveSignedSession(config SignedSessionConfig, record if err != nil { return err } + if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { + return err + } data, err := json.MarshalIndent(record, "", " ") if err != nil { return err diff --git a/go_backend/progress.go b/go_backend/progress.go index 0bc55690..2d8b81ee 100644 --- a/go_backend/progress.go +++ b/go_backend/progress.go @@ -3,6 +3,7 @@ package gobackend import ( "encoding/json" "math" + "sort" "sync" "time" ) @@ -334,6 +335,11 @@ func SetItemFinalizing(itemID string) { } } +// maxRemovedProgressEntries bounds the removal tombstones a long batch session +// can accumulate; pruning bumps multiProgressReset so lagging delta clients +// fall back to a full resync instead of missing removals. +const maxRemovedProgressEntries = 512 + func RemoveItemProgress(itemID string) { multiMu.Lock() defer multiMu.Unlock() @@ -341,10 +347,30 @@ func RemoveItemProgress(itemID string) { if _, ok := multiProgress.Items[itemID]; ok { delete(multiProgress.Items, itemID) removedProgressSeq[itemID] = nextMultiProgressSeqLocked() + if len(removedProgressSeq) > maxRemovedProgressEntries { + pruneRemovedProgressLocked() + } } markMultiProgressDirtyLocked() } +func pruneRemovedProgressLocked() { + revisions := make([]int64, 0, len(removedProgressSeq)) + for _, revision := range removedProgressSeq { + revisions = append(revisions, revision) + } + sort.Slice(revisions, func(i, j int) bool { return revisions[i] < revisions[j] }) + cutoff := revisions[len(revisions)/2] + for id, revision := range removedProgressSeq { + if revision <= cutoff { + delete(removedProgressSeq, id) + } + } + if cutoff > multiProgressReset { + multiProgressReset = cutoff + } +} + func GetItemProgress(itemID string) string { multiMu.RLock() defer multiMu.RUnlock()