Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
c1d57cb
ci: Add test to test that request times are not degrading
kirre-bylund Nov 12, 2024
2798238
fix: Make client auto retry 500, 502, and 503
kirre-bylund Nov 12, 2024
34a2a8f
refactor: Move LootLocker Json definitions to it's own file
kirre-bylund Nov 12, 2024
767084a
refactor: Move LootLockerHTTPMethod to endpoint definitions
kirre-bylund Nov 12, 2024
4d9a13b
refactor: Move LootLockerResponse, ErrorData, and pagination to own f…
kirre-bylund Nov 12, 2024
7a27156
refactor: Move Rate Limiter to separate file
kirre-bylund Nov 12, 2024
bad4046
ci: Move Json and RateLimiter tests from old test project
kirre-bylund Nov 12, 2024
ac8cd30
feature: Add Update method to LootLockerServerApi.cs
kirre-bylund Nov 12, 2024
00899b1
refactor: Move caller role placement into the endpoint definitions
kirre-bylund Nov 12, 2024
916e653
refactor: Remove unused LootLockerServerRequest constructor
kirre-bylund Nov 12, 2024
04b04e2
refactor: Split refactored and legacy HTTP stack
kirre-bylund Nov 12, 2024
aee38ae
refactor: Remove unused server request field payload
kirre-bylund Nov 12, 2024
37c47fc
refactor: Move different content types into different structures
kirre-bylund Nov 12, 2024
cbcc957
refactor: Break out request data structure from call chain
kirre-bylund Nov 13, 2024
755cdf6
refactor: Unify request flows CallAPI and UploadFile
kirre-bylund Nov 13, 2024
2db6772
ci: Add simple player files test to sanity test that upload works
kirre-bylund Nov 13, 2024
6d63b06
fix: Remove leftover game object tagging
kirre-bylund Nov 13, 2024
a5fac7e
refactor: Rename HTTP Client and break out coroutine
kirre-bylund Nov 13, 2024
332d600
refactor: Inline convenience method GetUrl
kirre-bylund Nov 13, 2024
119a3e0
refactor: Move Callback into request struct
kirre-bylund Nov 13, 2024
a9fbd9f
refactor: Move url and request creation to Request struct
kirre-bylund Nov 13, 2024
91f77a7
feature: Give request data a unique generated id
kirre-bylund Nov 13, 2024
4aaf36b
refactor: Refactor session refresh mechanic
kirre-bylund Nov 13, 2024
65e03e1
ci: Add simple session refresh test
kirre-bylund Nov 13, 2024
7ecf409
ci: Add test to test simultaneous requests during refactoring
kirre-bylund Nov 13, 2024
059d5f1
ci: Add test to test that simultaneous identical request are grouped
kirre-bylund Nov 13, 2024
c30ef79
feature!: Add HTTP Execution Queue
kirre-bylund Nov 13, 2024
f061a2b
fix: Fix request grouping
kirre-bylund Nov 13, 2024
1255c11
fix: Remove unused imports
kirre-bylund Nov 13, 2024
213e9df
refactor: Split request processing and result handling
kirre-bylund Nov 14, 2024
6ea7d13
feature: Add incremental backoff to the execution queue
kirre-bylund Nov 14, 2024
3ac97e3
feature: Add throttling and overload warning to HTTP Execution Queue
kirre-bylund Nov 14, 2024
319c4b7
fix: Stop bundling requests
kirre-bylund Nov 14, 2024
d6da1b4
fix: Move times retried incrementing to after backoff calc
kirre-bylund Nov 14, 2024
e621968
fix: Don't increment times retried twice for refresh session
kirre-bylund Nov 14, 2024
816d7a5
fix: Handle long retry after headers (over timeout) as failed retries
kirre-bylund Nov 14, 2024
a1c3ec8
fix: Update incremental backoff calculations
kirre-bylund Nov 14, 2024
71a2307
feature: Deny incoming requests when the execution queue is backed up
kirre-bylund Nov 14, 2024
7726035
Bump version to 4.0.0 because of stack updates
kirre-bylund Nov 14, 2024
d11b6ba
fix: Support hash combinations for Unity<v2021
kirre-bylund Nov 14, 2024
b68edc6
ci: Remove TDD tests for request time degradation, should not be on t…
kirre-bylund Nov 20, 2024
032e6cb
fix: Invert HTTP Execution Queue ifdef to slow burn into main
kirre-bylund Nov 20, 2024
542aa52
ci: Add intermittent building with HTTP Execution Queue in ci
kirre-bylund Nov 20, 2024
7e2282a
fix: Add namespace to Execution Queue Item
kirre-bylund Nov 20, 2024
bcb7a80
meta: Remove all CRLF line endings
kirre-bylund Nov 20, 2024
418548a
fix: Stop using JsonOptions when using newtonsoft in ListEntitlements
kirre-bylund Nov 20, 2024
db8bc07
ci: Add playmode test dependency to newtonsoft if needed
kirre-bylund Nov 20, 2024
878db34
feature: Update Newtonsoft version to 3.2.1 for ci
kirre-bylund Nov 21, 2024
e3cf487
ci: Make whether we use HTTP Execution Queue or not for CI configurable
kirre-bylund Nov 21, 2024
4506902
fix: Properly dispose of unity web requests
kirre-bylund Jan 9, 2025
2f11846
Cleanup after rebase
kirre-bylund Jan 9, 2025
f49ae29
fix: Process execution queue in editor as well
kirre-bylund Jan 9, 2025
21ad9be
fix: Stop retrying authenticationrequests on 401
kirre-bylund Jan 9, 2025
3790a34
fix: Null check response in leaderboard test
kirre-bylund Jan 9, 2025
88da18d
fix: Parse result for completed requests if it hasn't been done
kirre-bylund Jan 10, 2025
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
11 changes: 9 additions & 2 deletions .github/workflows/run-tests-and-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@ jobs:
run: |
if [[ ${{ github.event_name == 'workflow_dispatch' }} == true ]]; then echo "LOOTLOCKER_URL=${{ INPUTS.LL_URL }}" | sed -e 's/https:\/\///g' >> $GITHUB_ENV; elif [ ${{ vars.LL_USE_STAGE }} == 'true' ]; then echo "LOOTLOCKER_URL=${{ SECRETS.LOOTLOCKER_API_STAGE_URL }}" | sed -e 's/https:\/\///g' >> $GITHUB_ENV; else echo "LOOTLOCKER_URL=${{ SECRETS.LOOTLOCKER_API_PRODUCTION_URL }}" | sed -e 's/https:\/\///g' >> $GITHUB_ENV; fi
if [[ ${{ github.event_name == 'workflow_dispatch' }} == true ]]; then echo "TARGET_ENVIRONMENT=CUSTOM" >> $GITHUB_ENV; echo "USE_TAILSCALE=true" >> $GITHUB_ENV; elif [ ${{ vars.LL_USE_STAGE }} == 'true' ]; then echo "TARGET_ENVIRONMENT=STAGE" >> $GITHUB_ENV; echo "USE_TAILSCALE=true" >> $GITHUB_ENV; else echo "TARGET_ENVIRONMENT=PRODUCTION" >> $GITHUB_ENV; echo "USE_TAILSCALE=false" >> $GITHUB_ENV; fi
COINFLIP=$(($RANDOM%${{ vars.LL_USE_LEGACY_HTTP_ONE_IN }}))
if [[ $COINFLIP -lt 1 ]]; then echo "USE_HTTP_EXECUTION_QUEUE=false" >> $GITHUB_ENV; else echo "USE_HTTP_EXECUTION_QUEUE=true"; fi
- name: Checkout this repository
uses: actions/checkout@v4
with:
Expand All @@ -361,7 +363,7 @@ jobs:
mkdir TestProject
mkdir TestProject/Packages
DEPENDENCY_STRING=$'{\n "dependencies": {\n "com.lootlocker.lootlockersdk": "file:../../sdk"'
if [[ ${{ matrix.jsonLibrary == 'newtonsoft' }} ]]; then DEPENDENCY_STRING=$DEPENDENCY_STRING$',\n "com.unity.nuget.newtonsoft-json": "3.0.2"'; fi
if [[ ${{ matrix.jsonLibrary == 'newtonsoft' }} ]]; then DEPENDENCY_STRING=$DEPENDENCY_STRING$',\n "com.unity.nuget.newtonsoft-json": "3.2.1"'; fi
DEPENDENCY_STRING=$DEPENDENCY_STRING$'\n },\n "testables": ["com.lootlocker.lootlockersdk"]\n}'
echo $DEPENDENCY_STRING >> TestProject/Packages/manifest.json
mkdir TestProject/Assets/
Expand All @@ -385,7 +387,12 @@ jobs:
if: ${{ matrix.jsonLibrary == 'newtonsoft' }}
run: |
mkdir TestProject/ProjectSettings
echo $'%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!129 &1\nPlayerSettings:\n scriptingDefineSymbols:\n 1: LOOTLOCKER_USE_NEWTONSOFTJSON;LOOTLOCKER_COMMANDLINE_SETTINGS' >> TestProject/ProjectSettings/ProjectSettings.asset
echo $'%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!129 &1\nPlayerSettings:\n scriptingDefineSymbols:\n 1: LOOTLOCKER_COMMANDLINE_SETTINGS;LOOTLOCKER_USE_NEWTONSOFTJSON' >> TestProject/ProjectSettings/ProjectSettings.asset
sed -i -e 's/"nunit.framework.dll"/"nunit.framework.dll",\n\t\t"Newtonsoft.Json.dll"/g' sdk/Tests/LootLockerTests/PlayMode/PlayModeTests.asmdef
- name: Use HTTP Execution Queue
if: ${{ ENV.USE_HTTP_EXECUTION_QUEUE != 'true' }}
run: |
sed -i -e 's/1: LOOTLOCKER_COMMANDLINE_SETTINGS/1: LOOTLOCKER_BETA_HTTP_QUEUE;LOOTLOCKER_TARGET_STAGE_ENV/g' TestProject/ProjectSettings/ProjectSettings.asset
- name: Set user information command line arguments
if: ${{ ENV.USE_TAILSCALE != 'true' }}
run: |
Expand Down
14 changes: 9 additions & 5 deletions Runtime/Client/EndPointClass.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System;
using LootLocker;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LootLocker.LootLockerEnums;

namespace LootLocker.LootLockerEnums
{
public enum LootLockerCallerRole { User, Admin, Player, Base };
}

namespace LootLocker
{
Expand All @@ -11,13 +13,15 @@ public class EndPointClass
{
public string endPoint { get; set; }
public LootLockerHTTPMethod httpMethod { get; set; }
public LootLockerCallerRole callerRole { get; set; }

public EndPointClass() { }

public EndPointClass(string endPoint, LootLockerHTTPMethod httpMethod)
public EndPointClass(string endPoint, LootLockerHTTPMethod httpMethod, LootLockerCallerRole callerRole = LootLockerCallerRole.User)
{
this.endPoint = endPoint;
this.httpMethod = httpMethod;
this.callerRole = callerRole;
}
}
}
29 changes: 22 additions & 7 deletions Runtime/Client/LootLockerEndPoints.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Expand Down Expand Up @@ -37,12 +38,12 @@ public class LootLockerEndPoints

// White Label Login
[Header("White Label Login")]
public static EndPointClass whiteLabelSignUp = new EndPointClass("white-label-login/sign-up", LootLockerHTTPMethod.POST);
public static EndPointClass whiteLabelLogin = new EndPointClass("white-label-login/login", LootLockerHTTPMethod.POST);
public static EndPointClass whiteLabelVerifySession = new EndPointClass("white-label-login/verify-session", LootLockerHTTPMethod.POST);
public static EndPointClass whiteLabelRequestPasswordReset = new EndPointClass("white-label-login/request-reset-password", LootLockerHTTPMethod.POST);
public static EndPointClass whiteLabelSignUp = new EndPointClass("white-label-login/sign-up", LootLockerHTTPMethod.POST, LootLockerEnums.LootLockerCallerRole.Base);
public static EndPointClass whiteLabelLogin = new EndPointClass("white-label-login/login", LootLockerHTTPMethod.POST, LootLockerEnums.LootLockerCallerRole.Base);
public static EndPointClass whiteLabelVerifySession = new EndPointClass("white-label-login/verify-session", LootLockerHTTPMethod.POST, LootLockerEnums.LootLockerCallerRole.Base);
public static EndPointClass whiteLabelRequestPasswordReset = new EndPointClass("white-label-login/request-reset-password", LootLockerHTTPMethod.POST, LootLockerEnums.LootLockerCallerRole.Base);
public static EndPointClass whiteLabelRequestAccountVerification = new EndPointClass("white-label-login/request-verification", LootLockerHTTPMethod.POST);
public static EndPointClass whiteLabelLoginSessionRequest = new EndPointClass("v2/session/white-label", LootLockerHTTPMethod.POST);
public static EndPointClass whiteLabelLoginSessionRequest = new EndPointClass("v2/session/white-label", LootLockerHTTPMethod.POST, LootLockerEnums.LootLockerCallerRole.Base);

// Player
[Header("Player")]
Expand Down Expand Up @@ -322,6 +323,20 @@ public class LootLockerEndPoints
public static EndPointClass ListNotifications = new EndPointClass("notifications/v1", LootLockerHTTPMethod.GET);
public static EndPointClass ReadNotifications = new EndPointClass("notifications/v1/read", LootLockerHTTPMethod.PUT);
public static EndPointClass ReadAllNotifications = new EndPointClass("notifications/v1/read/all", LootLockerHTTPMethod.PUT);
}

[Serializable]
public enum LootLockerHTTPMethod
{
GET = 0,
POST = 1,
DELETE = 2,
PUT = 3,
HEAD = 4,
CREATE = 5,
OPTIONS = 6,
PATCH = 7,
UPLOAD_FILE = 8,
UPDATE_FILE = 9
}
}
}
95 changes: 95 additions & 0 deletions Runtime/Client/LootLockerErrorData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
namespace LootLocker
{
public class LootLockerErrorData
{
public LootLockerErrorData(int httpStatusCode, string errorMessage)
{
code = $"HTTP{httpStatusCode}";
doc_url = $"https://developer.mozilla.org/docs/Web/HTTP/Status/{httpStatusCode}";
message = errorMessage;
}

public LootLockerErrorData() { }

/// <summary>
/// A descriptive code identifying the error.
/// </summary>
public string code { get; set; }

/// <summary>
/// A link to further documentation on the error.
/// </summary>
public string doc_url { get; set; }

/// <summary>
/// A unique identifier of the request to use in contact with support.
/// </summary>
public string request_id { get; set; }

/// <summary>
/// A unique identifier for tracing the request through LootLocker systems, use this in contact with support.
/// </summary>
public string trace_id { get; set; }

/// <summary>
/// If the request was not a success this property will hold any error messages
/// </summary>
public string message { get; set; }

/// <summary>
/// If the request was rate limited (status code 429) or the servers were temporarily unavailable (status code 503) you can use this value to determine how many seconds to wait before retrying
/// </summary>
public int? retry_after_seconds { get; set; } = null;

/// <summary>
/// An easy way of debugging LootLockerErrorData class, example: Debug.Log(onComplete.errorData);
/// </summary>
/// <returns>string used to debug errors</returns>
public override string ToString()
{
// Empty error, make sure we print something
if (string.IsNullOrEmpty(message) && string.IsNullOrEmpty(trace_id) && string.IsNullOrEmpty(request_id))
{
return $"An unexpected LootLocker error without error data occurred. Please try again later.\n If the issue persists, please contact LootLocker support.";
}

//Print the most important info first
string prettyError = $"LootLocker Error: \"{message ?? ""}\"";

// Look for intermittent, non user errors
if (!string.IsNullOrEmpty(code) && code.StartsWith("HTTP5"))
{
prettyError +=
$"\nTry again later. If the issue persists, please contact LootLocker support and provide the following error details:\n trace ID - \"{trace_id ?? ""}\",\n request ID - \"{request_id ?? ""}\",\n message - \"{message ?? ""}\".";
if (!string.IsNullOrEmpty(doc_url))
{
prettyError += $"\nFor more information, see {doc_url} (error code was \"{code}\").";
}
}
// Print user errors
else
{
prettyError +=
$"\nThere was a problem with your request. The error message provides information on the problem and will help you fix it.";
if (!string.IsNullOrEmpty(doc_url ?? ""))
{
prettyError += $"\nFor more information, see {doc_url ?? ""} (error code was \"{code ?? ""}\").";
}

prettyError +=
$"\nIf you are unable to fix the issue, contact LootLocker support and provide the following error details:";
if (!string.IsNullOrEmpty(trace_id ?? ""))
{
prettyError += $"\n trace ID - \"{trace_id}\"";
}
if (!string.IsNullOrEmpty(request_id))
{
prettyError += $"\n request ID - \"{request_id}\"";
}

prettyError += $"\n message - \"{message ?? ""}\".";
}
return prettyError;
}
}
}
2 changes: 2 additions & 0 deletions Runtime/Client/LootLockerErrorData.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading