Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions addons/sourcemod/scripting/include/offstyledb.inc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#include <offstyledb_shavit>

// TODO: 100MB is reserved unconditionally for bulk JSON payloads. If bulk
// ever switches to streaming/paging, shrink this.
#pragma dynamic 104857600
#pragma newdecls required
#pragma semicolon 1
Expand Down Expand Up @@ -173,6 +175,11 @@ public void OnAllPluginsLoaded()

public void OnConfigsExecuted()
{
// TODO: we read the key once and blank the ConVar so it doesn't leak via
// sm_cvar. The strlen guard makes a plugin reload re-read correctly
// (since we blanked the ConVar after), but the interaction is subtle -
// worth replacing with a proper secret-loading path (env var / sealed
// file) if one appears.
if (strlen(gS_AuthKey) == 0)
{
gCV_Authentication.GetString(gS_AuthKey, sizeof(gS_AuthKey));
Expand Down
18 changes: 10 additions & 8 deletions addons/sourcemod/scripting/include/offstyledb_bulk.inc
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ public Action Command_SendAllWRs(int client, int args)
if (gB_IsProcessingBatches)
{
ReplyToCommand(client, "[OSdb] Already processing batches. Please wait for current operation to complete.");
DebugPrint("Bulk operation request denied - already processing batches");
return Plugin_Handled;
}

// Flag immediately so a second osdb_get_all_wrs call doesn't slip through
// the guard while /bulk_verification and the SQL query are in flight.
// Every failure path below clears this back to false.
gB_IsProcessingBatches = true;

ReplyToCommand(client, "[OSdb] Requesting bulk verification...");
DebugPrint("Starting bulk verification request");
RequestBulkVerification();

return Plugin_Handled;
Expand Down Expand Up @@ -71,19 +74,17 @@ public void Callback_OnBulkVerification(HTTPResponse resp, any value)
if (resp.Status != HTTPStatus_OK || resp.Data == null)
{
LogError("[OSdb] Bulk verification failed: status = %d, data = null", resp.Status);
DebugPrint("Bulk verification failed with status %d", resp.Status);
gB_IsProcessingBatches = false;
return;
}

DebugPrint("Bulk verification response received successfully");

JSONObject data = view_as<JSONObject>(resp.Data);

if (!data.HasKey("key_to_send_times"))
{
LogError("[OSdb] Bulk verification response missing 'key_to_send_times' field");
DebugPrint("Bulk verification response missing required field");
delete data;
gB_IsProcessingBatches = false;
return;
}

Expand All @@ -106,7 +107,7 @@ void SendRecordDatabase()
if (bulkMode == -1)
{
PrintToServer("[OSdb] Bulk upload disabled (mode = -1), skipping record collection");
DebugPrint("Bulk upload skipped due to mode = -1");
gB_IsProcessingBatches = false;
return;
}

Expand Down Expand Up @@ -143,16 +144,17 @@ public void SQL_GetRecords_Callback(Database db, DBResultSet results, const char
if (results == null)
{
LogError("[OSdb] SQL_GetRecords_Callback results are null, SQL error: %s", error);
gB_IsProcessingBatches = false;
return;
}

if (results.RowCount == 0)
{
LogError("[OSdb] SQL_GetRecords_Callback rowcount is 0");
gB_IsProcessingBatches = false;
return;
}

gB_IsProcessingBatches = true;
gI_CurrentBatch = 0;
gI_TotalRecords = 0;

Expand Down
5 changes: 5 additions & 0 deletions addons/sourcemod/scripting/include/offstyledb_records.inc
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ void Records_HandleFinish(int client, int style, float time, int jumps, int stra
return;
}

// TODO: overwrite race - if player A stashed an intent, disconnected,
// player B took the slot and finished all before A's replay save fired,
// A's replay would dispatch B's intent. Requires B to complete a full
// map run in <100ms so practically impossible, but a steamid check
// before dispatch would close it.
gPending[client] = intent;
DebugPrint("Stashed intent for client %d (isWR=%d)", client, isWR);
}
Expand Down
6 changes: 6 additions & 0 deletions addons/sourcemod/scripting/include/offstyledb_styles.inc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#pragma newdecls required
#pragma semicolon 1

// TODO: shavit-styles.cfg is opened twice per call - once for HashStyleConfig
// and again below for the base64-encode + POST. Read once, hash the buffer,
// encode the buffer.
void GetStyleMapping(bool forceRefresh = false)
{
DebugPrint("Starting style mapping request (forceRefresh: %s)", forceRefresh ? "true" : "false");
Expand Down Expand Up @@ -131,6 +134,9 @@ public void Callback_OnStyleMapping(HTTPResponse resp, any value)

if (resp.Status != HTTPStatus_OK || resp.Data == null)
{
// TODO: retry on a short backoff instead of waiting for the next map
// change. If a map lasts hours, style submissions stay broken the
// whole time.
LogError("[OSdb] Style mapping fetch failed (status=%d). Keeping any existing mapping; will retry on next map change.", resp.Status);
// Invalidate the cached hash so the next OnMapEnd tries again even if
// shavit-styles.cfg didn't change in between.
Expand Down