mormot.rest.core--TRestBackgroundTimer
{ ************ 自定義 REST 執行 }
type
/// TRestServer.Uri() 方法可能執行的所有命令
// - execSoaByMethod 用於基於方法的服務
// - execSoaByInterface 用於基於介面的服務
// - execOrmGet 用於 ORM 讀取操作,即 Retrieve*() 方法
// - execOrmWrite 用於 ORM 寫入操作,即 Add、Update、Delete、TransactionBegin、Commit、Rollback 方法
TRestServerUriContextCommand = (
execNone,
execSoaByMethod,
execSoaByInterface,
execOrmGet,
execOrmWrite);
/// TRest 類執行讀取或寫入操作的方式
// - 用於例如 TRestServer.AcquireWriteMode 或
// TRestServer.AcquireExecutionMode/AcquireExecutionLockedTimeOut
TRestServerAcquireMode = (
amUnlocked,
amLocked,
amBackgroundThread,
amBackgroundOrmSharedThread,
amMainThread);
/// 用於儲存 TRest 例項的執行引數
TRestAcquireExecution = class(TSynPersistentLock)
public
/// 讀取或寫入操作的執行方式
Mode: TRestServerAcquireMode;
/// 在獲取鎖失敗前的毫秒延遲時間
LockedTimeOut: cardinal;
/// 後臺執行緒例項(如果有)
Thread: TSynBackgroundThreadMethod;
/// 終結記憶體結構以及相關聯的後臺執行緒
destructor Destroy; override;
end;
PRestAcquireExecution = ^TRestAcquireExecution;
/// 定義 TRest 類如何執行其 ORM 和 SOA 操作
TRestAcquireExecutions =
array[TRestServerUriContextCommand] of TRestAcquireExecution;
/// 伺服器端給定客戶端連線的真實識別符號
// - 另請參閱 mormot.net.http 中定義的 THttpServerConnectionID,可能對映
// http.sys ID,或來自遞增序列的 31 位真實值
TRestConnectionID = Int64;
const
/// 日誌大小(以位元組為單位),最多記錄 2 KB 的 JSON 響應,以節省空間
MAX_SIZE_RESPONSE_LOG = 2 shl 10;
/// 您可以使用此 cookie 值在瀏覽器端刪除 cookie
COOKIE_EXPIRED = '; Expires=Sat, 01 Jan 2010 00:00:01 GMT';
CONTENT_TYPE_WEBFORM: PAnsiChar = 'APPLICATION/X-WWW-FORM-URLENCODED';
CONTENT_TYPE_MULTIPARTFORM: PAnsiChar = 'MULTIPART/FORM-DATA';
{ ************ TRestBackgroundTimer 用於多執行緒處理 }
type
{$M+}
{ 由於內部耦合,這些類的已釋出屬性需要 RTTI 資訊,
因此這些類需要在單個 "type" 語句中定義 }
TRest = class;
{$M-}
/// 在 TRest.AsyncRedirect 後臺執行後可選呼叫
// - 以檢索任何輸出結果值,作為 JSON 編碼的內容
// - 在 TRestBackgroundTimer.AsyncBackgroundExecute 受保護方法中使用
TOnAsyncRedirectResult = procedure(const aMethod: TInterfaceMethod;
const aInstance: IInvokable; const aParams, aResult: RawUtf8) of object;
/// 能夠以定期速度執行一個或多個任務的執行緒,或進行
// 帶有適當 TRest 整合的非同步介面或批處理執行
// - 例如,由 TRest.TimerEnable/AsyncRedirect/AsyncBatchStart 方法使用
// - TRest.BackgroundTimer 將定義一個例項,但您可以建立
// 其他專用例項來例項化分離的執行緒
TRestBackgroundTimer = class(TSynBackgroundTimer)
protected
fRest: TRest;
fBackgroundBatch: TRestBatchLockedDynArray;
fBackgroundInterning: array of TRawUtf8Interning;
fBackgroundInterningMaxRefCount: integer;
fBackgroundInterningSafe: TLightLock; // 偏執鎖
procedure SystemUseBackgroundExecute(Sender: TSynBackgroundTimer; const Msg: RawUtf8);
// 用於 AsyncRedirect/AsyncBatch/AsyncInterning
function AsyncBatchIndex(aTable: TOrmClass): PtrInt;
function AsyncBatchLocked(aTable: TOrmClass; out aBatch: TRestBatchLocked): boolean;
procedure AsyncBatchUnLock(aBatch: TRestBatchLocked);
procedure AsyncBatchExecute(Sender: TSynBackgroundTimer; const Msg: RawUtf8);
procedure AsyncBackgroundExecute(Sender: TSynBackgroundTimer; const Msg: RawUtf8);
procedure AsyncBackgroundInterning(Sender: TSynBackgroundTimer; const Msg: RawUtf8);
public
/// 初始化執行緒以進行定期任務處理
constructor Create(aRest: TRest; const aThreadName: RawUtf8 = '';
aStats: TSynMonitorClass = nil); reintroduce; virtual;
/// 終結執行緒
destructor Destroy; override;
/// 在後臺執行緒中定義介面方法的非同步執行
// - 此方法透過一個偽類實現任何介面,該類將所有方法呼叫重定向到另一個介面的呼叫,
// 但作為 FIFO 在與 TimerEnable/TimerDisable 過程共享的後臺執行緒中執行
// - 引數將被序列化為 JSON 並儲存在佇列中
// - 按設計,僅允許沒有輸出引數的過程方法,因為它們的執行將非同步進行
// - 當然,在 aDestinationInterface 方法執行中引入了輕微的延遲,但主處理執行緒不再延遲,
// 並且避免了潛在的競態條件
// - 返回的偽 aCallbackInterface 應在銷燬 TRest 之前釋放,以釋放重定向資源
// - 這是解決 SOA 回撥中最難實現問題的優雅方案,即避免重入時的競態條件,
// 例如,如果回撥從一個執行緒執行,然後回撥程式碼嘗試在初始執行緒的上下文中執行某些操作(由臨界區(互斥鎖)保護)
procedure AsyncRedirect(const aGuid: TGuid;
const aDestinationInterface: IInvokable; out aCallbackInterface;
const aOnResult: TOnAsyncRedirectResult = nil); overload;
/// 在後臺執行緒中定義介面方法的非同步執行(過載版本)
// - 功能與上一個 AsyncRedirect 方法類似,但允許透過 TInterfacedObject 例項指定目標
procedure AsyncRedirect(const aGuid: TGuid;
const aDestinationInstance: TInterfacedObject; out aCallbackInterface;
const aOnResult: TOnAsyncRedirectResult = nil); overload;
/// 準備在後臺執行緒中執行的非同步 ORM BATCH 過程
// - 將初始化 TRestBatch 並呼叫 TimerEnable 以初始化後臺執行緒,根據給定的處理週期(以秒為單位),
// 或 TRestBatch.Count 閾值來呼叫 BatchSend
// - 實際的 REST/CRUD 命令將透過 AsyncBatchAdd、AsyncBatchUpdate 和 AsyncBatchDelete 方法進行
// - 除非使用 AsyncBatchStop 方法重新整理當前的非同步 BATCH,否則每個表只允許呼叫一次 AsyncBatch()
// - 在專用執行緒中使用 BATCH 將允許非常快速的後臺非同步處理 ORM 方法,足以滿足大多數用例
function AsyncBatchStart(Table: TOrmClass;
SendSeconds: integer; PendingRowThreshold: integer = 500;
AutomaticTransactionPerRow: integer = 1000;
Options: TRestBatchOptions = [boExtendedJson]): boolean;
/// 終結在後臺執行緒中執行的非同步 ORM BATCH 過程
// - 應先呼叫 AsyncBatch(),否則返回 false
// - Table=nil 將釋放所有現有的 batch 例項
function AsyncBatchStop(Table: TOrmClass): boolean;
/// 在要在後臺執行緒中寫入的 BATCH 中建立一個新的 ORM 成員
// - 應先呼叫 AsyncBatchStart(),否則返回 -1
// - 是 Timer 執行緒中傳送的 TRestBatch.Add() 的包裝器,
// 因此將返回 BATCH 行中的索引,而不是建立的 TID
// - 此方法是執行緒安全的
function AsyncBatchAdd(Value: TOrm; SendData: boolean;
ForceID: boolean = false; const CustomFields: TFieldBits = [];
DoNotAutoComputeFields: boolean = false): integer;
/// 在要在後臺執行緒中寫入的 BATCH 中附加一些 JSON 內容
// - 可用於模擬已預先計算 JSON 物件的 AsyncBatchAdd()
// - 是 Timer 執行緒中傳送的 TRestBatch.RawAdd() 的包裝器,
// 因此將返回 BATCH 行中的索引,而不是建立的 TID
// - 此方法是執行緒安全的
function AsyncBatchRawAdd(Table: TOrmClass; const SentData: RawUtf8): integer;
/// 在要在後臺執行緒中寫入的 BATCH 中附加一些 JSON 內容
// - 可用於模擬已儲存在 TJsonWriter 例項中的 AsyncBatchAdd()
// - 是 Timer 執行緒中 TRestBatch.RawAppend.AddNoJsonEscape(SentData) 的包裝器
// - 此方法是執行緒安全的
procedure AsyncBatchRawAppend(Table: TOrmClass; SentData: TJsonWriter);
/// 在後臺執行緒中要寫入的 BATCH 中更新 ORM 成員
// - 應先呼叫 AsyncBatchStart(),否則返回 -1
// - 是 Timer 執行緒中傳送的 TRestBatch.Update() 的包裝器
// - 此方法是執行緒安全的
function AsyncBatchUpdate(Value: TOrm;
const CustomFields: TFieldBits = [];
DoNotAutoComputeFields: boolean = false): integer;
/// 在後臺執行緒中要寫入的 BATCH 中刪除 ORM 成員
// - 應先呼叫 AsyncBatchStart(),否則返回 -1
// - 是 Timer 執行緒中傳送的 TRestBatch.Delete() 的包裝器
// - 此方法是執行緒安全的
function AsyncBatchDelete(Table: TOrmClass; ID: TID): integer;
/// 允許對指定的 RawUtf8 字串池進行後臺垃圾收集
// - 預設情況下,將每 5 分鐘執行 Interning.Clean(2)
// - 設定 InterningMaxRefCount=0 以禁用 Interning 例項的處理過程
procedure AsyncInterning(Interning: TRawUtf8Interning; InterningMaxRefCount: integer = 2; PeriodMinutes: integer = 5);
/// 直接訪問 TRest 例項所有者
property Rest: TRest read fRest;
/// 直接訪問後臺執行緒中的 TRestBatch 例項
property BackgroundBatch: TRestBatchLockedDynArray read fBackgroundBatch;
published
/// 執行緒的識別符號,用於日誌記錄
property Name: RawUtf8 read fThreadName;
end;
// 向後相容型別重定向
{$ifndef PUREMORMOT2}
TSqlRestServerUriContextCommand = TRestServerUriContextCommand;
TSqlRestServerAcquireMode = TRestServerAcquireMode;
TSqlRestAcquireExecution = TRestAcquireExecution;
TSqlRestBackgroundTimer = TRestBackgroundTimer;
{$endif PUREMORMOT2}