167 lines
5.5 KiB
C
167 lines
5.5 KiB
C
|
|
// Fill out your copyright notice in the Description page of Project Settings.
|
|||
|
|
|
|||
|
|
#pragma once
|
|||
|
|
|
|||
|
|
#include "CoreMinimal.h"
|
|||
|
|
#include "UObject/Object.h"
|
|||
|
|
#include "Containers/Queue.h"
|
|||
|
|
#include "Tickable.h"
|
|||
|
|
#include "Struct/DTFluxRequestStructs.h"
|
|||
|
|
#include "Struct/DTFluxServerResponseStruct.h"
|
|||
|
|
#include "Types/Enum/DTFluxCoreEnum.h"
|
|||
|
|
#include "DTFluxQueuedManager.generated.h"
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief Structure représentant une requête en file d'attente avec ses métadonnées
|
|||
|
|
*/
|
|||
|
|
USTRUCT(BlueprintType)
|
|||
|
|
struct FDTFluxQueuedRequest : public FDTFluxRequestBase
|
|||
|
|
{
|
|||
|
|
GENERATED_BODY()
|
|||
|
|
|
|||
|
|
/** L'identifiant unique de la requête */
|
|||
|
|
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
|||
|
|
FGuid RequestId;
|
|||
|
|
|
|||
|
|
/** L'heure à laquelle la requête a été envoyée */
|
|||
|
|
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
|||
|
|
FDateTime CreatedAt;
|
|||
|
|
|
|||
|
|
/** Le type de requête */
|
|||
|
|
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
|||
|
|
EDTFluxApiDataType RequestType = EDTFluxRequestType::None;
|
|||
|
|
|
|||
|
|
/** Identifiant de la compétition (ContestId) */
|
|||
|
|
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
|||
|
|
int32 ContestId = -1;
|
|||
|
|
|
|||
|
|
/** Identifiant de l'étape (StageId) */
|
|||
|
|
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
|||
|
|
int32 StageId = -1;
|
|||
|
|
|
|||
|
|
/** Identifiant du split (SplitId) */
|
|||
|
|
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
|||
|
|
int32 SplitId = -1;
|
|||
|
|
|
|||
|
|
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
|||
|
|
FString RawResponse = "";
|
|||
|
|
|
|||
|
|
/** Délai maximum avant que la requête soit considérée comme expirée (en secondes) */
|
|||
|
|
UPROPERTY(BlueprintReadWrite, Category = "DTFlux|Request")
|
|||
|
|
float TimeoutSeconds = 2.0f;
|
|||
|
|
|
|||
|
|
/** Determine si la requête peut être mise en cache */
|
|||
|
|
UPROPERTY(BlueprintReadWrite, Category = "DTFlux|Request")
|
|||
|
|
bool bIsCacheable = false;
|
|||
|
|
|
|||
|
|
/** Validité du cache si bIsCacheable est mis à true après reception de la réponse (en secondes) */
|
|||
|
|
UPROPERTY(BlueprintReadWrite, Category = "DTFlux|Request")
|
|||
|
|
float CachedValidity = 50.0f;
|
|||
|
|
|
|||
|
|
/** Indicateur si la requête a reçu une réponse */
|
|||
|
|
UPROPERTY(BlueprintReadWrite, Category = "DTFlux|Request")
|
|||
|
|
bool bHasReceivedResponse = false;
|
|||
|
|
|
|||
|
|
/** Constructeur par défaut */
|
|||
|
|
FDTFluxQueuedRequest()
|
|||
|
|
{
|
|||
|
|
RequestId = FGuid::NewGuid();
|
|||
|
|
CreatedAt = FDateTime::Now();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** Constructeur avec paramètres */
|
|||
|
|
FDTFluxQueuedRequest(EDTFluxRequestType InRequestType, int32 InContestId = -1, int32 InStageId = -1,
|
|||
|
|
int32 InSplitId = -1)
|
|||
|
|
: RequestType(InRequestType)
|
|||
|
|
, ContestId(InContestId)
|
|||
|
|
, StageId(InStageId)
|
|||
|
|
, SplitId(InSplitId)
|
|||
|
|
{
|
|||
|
|
RequestId = FGuid::NewGuid();
|
|||
|
|
CreatedAt = FDateTime::Now();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool operator==(const FDTFluxQueuedRequest& Left) const
|
|||
|
|
{
|
|||
|
|
return RequestId == Left.RequestId;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool operator!=(const FDTFluxQueuedRequest& Left) const
|
|||
|
|
{
|
|||
|
|
return RequestId != Left.RequestId;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
const FString Serialize() const;
|
|||
|
|
|
|||
|
|
/** Vérifie si la requête a expiré */
|
|||
|
|
bool HasTimedOut() const
|
|||
|
|
{
|
|||
|
|
return (FDateTime::Now() - CreatedAt).GetTotalSeconds() > TimeoutSeconds;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/** Vérifie si cette requête correspond aux paramètres spécifiés */
|
|||
|
|
bool Matches(EDTFluxRequestType InRequestType, int32 InContestId = -1, int32 InStageId = -1,
|
|||
|
|
int32 InSplitId = -1) const
|
|||
|
|
{
|
|||
|
|
return RequestType == InRequestType &&
|
|||
|
|
(InContestId == -1 || ContestId == InContestId) &&
|
|||
|
|
(InStageId == -1 || StageId == InStageId) &&
|
|||
|
|
(InSplitId == -1 || SplitId == InSplitId);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRequestTimedOut, const FDTFluxQueuedRequest&, TimedOutRequest);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief Classe Tickable gérant les requêtes WebSockets qui ne sont pas traçables nativement par l'API.
|
|||
|
|
* Cette classe utilise TQueue pour gérer efficacement les requêtes en attente et vérifie leur état dans le tick.
|
|||
|
|
*/
|
|||
|
|
UCLASS()
|
|||
|
|
class DTFLUXNETWORK_API UDTFluxQueuedManager : public UObject, public FTickableGameObject
|
|||
|
|
{
|
|||
|
|
GENERATED_BODY()
|
|||
|
|
|
|||
|
|
public:
|
|||
|
|
/** Constructeur par défaut */
|
|||
|
|
UDTFluxQueuedManager();
|
|||
|
|
virtual ~UDTFluxQueuedManager() override;
|
|||
|
|
void Initialize();
|
|||
|
|
FGuid QueueRequest(EDTFluxRequestType RequestType, int32 ContestId = -1, int32 StageId = -1, int32 SplitId = -1,
|
|||
|
|
const FString& RawMessage = "");
|
|||
|
|
bool MarkRequestAsResponded(const FGuid& TargetRequestGuid);
|
|||
|
|
bool MarkRequestAsResponded(const FDTFluxQueuedRequest& TargetRequest);
|
|||
|
|
bool IsRequestPending(EDTFluxRequestType RequestType, int32 ContestId = -1, int32 StageId = -1, int32 SplitId = -1);
|
|||
|
|
FDTFluxQueuedRequest* GetRequestPending(EDTFluxRequestType RequestType, int32 ContestId = -1, int32 StageId = -1,
|
|||
|
|
int32 SplitId = -1);
|
|||
|
|
const FDTFluxQueuedRequest* GetRequest(const FGuid& SearchedGuid);
|
|||
|
|
int32 GetPendingRequestCount();
|
|||
|
|
int32 CleanupTimedOutRequests();
|
|||
|
|
int32 CleanCashedRequests();
|
|||
|
|
void ClearAllRequests();
|
|||
|
|
// bool TryProcessResponse(const FDTFluxServerResponse& Response);
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Interface FTickableGameObject
|
|||
|
|
virtual void Tick(float DeltaTime) override;
|
|||
|
|
virtual bool IsTickable() const override;
|
|||
|
|
virtual TStatId GetStatId() const override;
|
|||
|
|
virtual bool IsTickableWhenPaused() const override { return true; }
|
|||
|
|
virtual bool IsTickableInEditor() const override { return true; }
|
|||
|
|
// Interface ~FTickableGameObject
|
|||
|
|
|
|||
|
|
|
|||
|
|
UPROPERTY(BlueprintAssignable, Category = "DTFlux|Network")
|
|||
|
|
FOnRequestTimedOut OnRequestTimedOut;
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
TQueue<FDTFluxQueuedRequest, EQueueMode::Mpsc> PendingRequestsQueue;
|
|||
|
|
TQueue<FDTFluxQueuedRequest, EQueueMode::Mpsc> CompletedRequestsQueue;
|
|||
|
|
TQueue<FDTFluxQueuedRequest, EQueueMode::Mpsc> TimedOutRequestsQueue;
|
|||
|
|
|
|||
|
|
bool bIsInitialized;
|
|||
|
|
float CheckInterval;
|
|||
|
|
float TimeSinceLastCheck;
|
|||
|
|
};
|