首页 > 其他分享 >mormot.rest.core--TRestBackgroundTimer

mormot.rest.core--TRestBackgroundTimer

时间:2024-07-12 18:22:18浏览次数:9  
标签:core const -- TRest BATCH mormot 线程 后台 procedure

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}

标签:core,const,--,TRest,BATCH,mormot,线程,后台,procedure
From: https://www.cnblogs.com/hieroly/p/18299096

相关文章

  • spark-submit提交任务时执行流程(简单版)
    yarncluster模式提交spark任务(1)执行脚本提交任务,实际是启动一个SparkSubmit的JVM进程。(2)SparkSubmit类中的main方法反射调用YarnClusterApplication的main方法。(3)YarnClusterApplication创建Yarn客户端,然后向yarn服务器发送执行指令:bin/javaApplicationMaster。(4)Yarn(Resour......
  • 【Springboot】玩转复杂单元测试启动类-只测试数据访问层(JPA+Mybatis) 和服务层 以及
    上一篇文章写了一个最复杂的SpringBootTest启动类,定制化程序奇高,然而有时候仅测试JPA是不够的。启动类需求:测试SpringDataJPA测试Mybatis从容器中获得ObjectMapper测试单独的Service使用TestNG或者使用Junit阻止Dubbo、Kafka、ElasticSearch等中间件启动使用appl......
  • 字符集相关知识
    什么是字符集?字符集又称字符编码,在计算机中所有数据都是二进制形式,包括abc@#$。字符编码规定了用哪些二进制数表示哪些符号。 ASCII编码单字节表示法,有一个扩充bit,另外7bit可以表示128个字符,其中有33个控制和95个可显示字符。 helloworldASCII68656C6C6......
  • 音视频开发基础知识
    视频解码解复用(Demux):解复用也可叫解封装。这里有一个概念叫封装格式,封装格式指的是音视频的组合格式,常见的有mp4、flv、mkv等。通俗来讲,封装是将音频流、视频流、字幕流以及其他附件按一定规则组合成一个封装的产物。而解封装起着与封装相反的作用,将一个流媒体文件拆解成音频......
  • 7-LinkedHashSet底层结构和源码分析
    7-LinkedHashSet底层结构和源码分析介绍汇总:LinkedHashSet全面说明LinkedHashSet底层机制说明1-LinkedHashSet全面说明LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组+双向链表。由于LinkedHashMap是继承HashMap的所有特性的,其双向链表是在原本的数......
  • 开通免费企业域名邮箱流程
    利用163开通免费的企业域名邮箱域名购买在此以腾讯云为例登录后先去完善实名认证信息个人建议二级域名和公司名称相关,简短好记个人建议一级域名选择com、cn、cc、net、top等一级域名找到喜欢的域名后,注意下拉查看续费价格,是否可以接受确认好价格和购买时间,然后选......
  • Maven的setting.xml镜像和私服配置.md
    <repository>和<mirror>在Maven中,和配置项分别出现在不同的配置文件中,并且它们有各自的作用和执行顺序。以下是这些配置项的详细说明和它们之间的关系:<repository>inpom.xml位置:位于项目的pom.xml文件中。作用:定义了特定项目构建时使用的远程仓库,通常用于解决项目依赖的......
  • Iceberg metrics导致的问题
    一、问题描述在icebergrewrite时报错:org.apache.iceberg.exceptions.ValidationException:Cannotcommit,foundnewdeleteforreplaceddatafile看信息像是对于要删除的DataFile,有新的DeleteFile作用于它,不应该直接删除DataFile。但是我们很明确并没有DeleteFile作用于其......
  • 常曲率空间分类问题
    推论12.5(常曲率流形的单值化定理)完整、连通的\(n\)维黎曼流形\((M,g)\)如果具有常截面曲率,则在等距意义下,正是形如\(\widetilde{M}/\Gamma\)的黎曼商,这里\(\widetilde{M}\)是常曲率模型空间\(\mathbb{R}^n\)、\(\mathbb{S}^n(R)\)或\(\mathbb{H}^n(R)\)之一,\(\G......
  • 6. DRF 版本
    目录DjangoDRF版本1.使用1.1URL传递version参数DjangoDRF版本1.使用rest_framework的versioning.py中定义了多种方法,支持不同方式携带version信息,比如支持url/hostname/namespace中携带并传递version信息1.1URL传递version参数https://127.0.0.1:8000/user/?ve......