MCPcopy Create free account
hub / github.com/Selectively11/CloudRedirect / HandleBeginBatch

Function HandleBeginBatch

src/common/rpc_handlers.cpp:1422–1493  ·  view source on GitHub ↗

BeginAppUploadBatch

Source from the content-addressed store, hash-verified

1420
1421// BeginAppUploadBatch
1422RpcResult HandleBeginBatch(uint32_t appId, const std::vector<PB::Field>& reqBody) {
1423 uint64_t batchId = BatchTracker_NextId();
1424 uint32_t accountId = 0;
1425 if (!RequireAccountId("BeginAppUploadBatch", appId, accountId)) {
1426 // Fail early: error skips CompleteBatch, preventing orphaned local blobs.
1427 return RpcResult(PB::Writer(), kEResultFail);
1428 }
1429
1430 // If a previous batch's cloud publish is still in-flight, wait for it so
1431 // FetchCloudStateForServe sees the fresh CN. Typically a no-op (single batch)
1432 // or instant (publish already landed between batches).
1433 CloudStorage::WaitForPendingPublish(accountId, appId);
1434
1435 // The CN returned here is what Steam records as synced and what we must publish
1436 // at CompleteBatch -- they have to match, or Steam re-downloads what it just
1437 // uploaded. Assign max(local, cloud)+1, strictly above whatever the cloud holds.
1438 uint64_t localCN = LocalStorage::GetChangeNumber(accountId, appId);
1439 uint64_t cloudCN = 0;
1440 if (CloudStorage::IsCloudActive()) {
1441 // Runs on Steam's BeginAppUploadBatch thread; time it (serve-cached, usually
1442 // fast, but a cache miss does a live fetch that could stall the main loop).
1443 auto tbb = std::chrono::steady_clock::now();
1444 auto cloud = CloudStorage::FetchCloudStateForServe(accountId, appId);
1445 auto bbMs = std::chrono::duration_cast<std::chrono::milliseconds>(
1446 std::chrono::steady_clock::now() - tbb).count();
1447 if (bbMs > 500)
1448 LOG("[NS] BeginBatch app=%u: FetchCloudStateForServe took %lldms "
1449 "(on Steam's thread)", appId, (long long)bbMs);
1450 if (cloud.status == CloudStorage::StateFetchStatus::Ok) {
1451 cloudCN = cloud.state.cn;
1452 } else if (cloud.status != CloudStorage::StateFetchStatus::NotFound) {
1453 // Cloud CN unknown: assigning localCN+1 could regress the cloud CN.
1454 // Fail the batch; Steam retries once the fetch resolves.
1455 LOG("[NS] BeginBatch app=%u: cloud CN unverifiable (status=%d) -- failing batch "
1456 "to avoid regressive CN; Steam will retry", appId,
1457 static_cast<int>(cloud.status));
1458 return RpcResult(PB::Writer(), kEResultFail);
1459 }
1460 }
1461 uint64_t assignedCN = (std::max)(localCN, cloudCN) + 1;
1462 uint64_t appBuildId = 0;
1463 PrepareBatchCanonicalTokens(accountId, appId);
1464 PendingOpsJournal::RecordUploadBatchStart(accountId, appId);
1465
1466 int uploadCount = 0, deleteCount = 0;
1467 for (auto& f : reqBody) {
1468 if (f.fieldNum == 3 && f.wireType == PB::LengthDelimited) {
1469 std::string name(reinterpret_cast<const char*>(f.data), f.dataLen);
1470 LOG("[NS-BATCH] upload: %s", SanitizeForLog(name).c_str());
1471 TryCaptureRootToken(accountId, appId,
1472 CanonicalizeUploadRootToken(accountId, appId, StripRootToken(name), ExtractRootToken(name)));
1473 ++uploadCount;
1474 }
1475 if (f.fieldNum == 4 && f.wireType == PB::LengthDelimited) {
1476 std::string name(reinterpret_cast<const char*>(f.data), f.dataLen);
1477 LOG("[NS-BATCH] delete: %s", SanitizeForLog(name).c_str());
1478 TryCaptureRootToken(accountId, appId,
1479 CanonicalizeUploadRootToken(accountId, appId, StripRootToken(name), ExtractRootToken(name)));

Callers 3

CR_HandleCloudRpcFunction · 0.85
DispatchCloudRpcFunction · 0.85
DispatchCloudRpcFunction · 0.85

Calls 15

BatchTracker_NextIdFunction · 0.85
RequireAccountIdFunction · 0.85
RpcResultClass · 0.85
WriterClass · 0.85
WaitForPendingPublishFunction · 0.85
GetChangeNumberFunction · 0.85
IsCloudActiveFunction · 0.85
FetchCloudStateForServeFunction · 0.85
RecordUploadBatchStartFunction · 0.85
SanitizeForLogFunction · 0.85
TryCaptureRootTokenFunction · 0.85

Tested by

no test coverage detected