1
0
mirror of synced 2026-04-25 01:38:38 +08:00

auto commit

This commit is contained in:
yitter
2022-10-17 11:34:58 +08:00
parent c029cded3c
commit f57d9f1de6
18 changed files with 2315 additions and 2 deletions

View File

@@ -0,0 +1,404 @@
unit uSnowWorkerM1;
interface
uses
uISnowWorker, uIdGeneratorOptions, System.SyncObjs, uTOverCostActionArg, System.DateUtils, System.SysUtils;
/// <summary>
/// ѩ<><D1A9>Ư<EFBFBD><C6AF><EFBFBD>
/// </summary>
type
TSnowWorkerM1 = class(TInterfacedObject, ISnowWorker)
private
// private static long _StartTimeTick = 0;
// private static long _BaseTimeTick = 0;
protected
SyncLock: TCriticalSection;
protected
// FBaseTime: TDateTime;
FBaseTime: Int64;
FWorkerId: Word;
FWorkerIdBitLength: Byte;
FSeqBitLength: Byte;
FMaxSeqNumber: Integer;
FMinSeqNumber: Word;
FTopOverCostCount: Integer;
//
FTimestampShift: Byte;
FCurrentSeqNumber: Word;
FLastTimeTick: Int64;
FTurnBackTimeTick: Int64;
FTurnBackIndex: Byte;
FIsOverCost: Boolean;
FOverCostCountInOneTerm: Integer;
//
FGenCountInOneTerm: Integer;
FTermIndex: Integer;
protected
/// <summary>
/// <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
/// </summary>
// property BaseTime: TDateTime read FBaseTime write FBaseTime;
property BaseTime: Int64 read FBaseTime;
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
property WorkerId: Word read FWorkerId default 0;
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>
/// </summary>
property WorkerIdBitLength: Byte read FWorkerIdBitLength default 0;
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>
/// </summary>
property SeqBitLength: Byte read FSeqBitLength default 0;
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
property MaxSeqNumber: Integer read FMaxSeqNumber default 0;
/// <summary>
/// <20><>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
property MinSeqNumber: Word read FMinSeqNumber default 0;
/// <summary>
/// <20><><EFBFBD><EFBFBD>Ư<EFBFBD>ƴ<EFBFBD><C6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
property TopOverCostCount: Integer read FTopOverCostCount write FTopOverCostCount default 0;
//
property TimestampShift: Byte read FTimestampShift write FTimestampShift default 0;
//
property CurrentSeqNumber: Word read FCurrentSeqNumber write FCurrentSeqNumber;
property LastTimeTick: Int64 read FLastTimeTick write FLastTimeTick default 0; // -1L
property TurnBackTimeTick: Int64 read FTurnBackTimeTick write FTurnBackTimeTick default 0; // -1L;
property TurnBackIndex: Byte read FTurnBackIndex write FTurnBackIndex default 0;
property IsOverCost: Boolean read FIsOverCost write FIsOverCost default False;
property OverCostCountInOneTerm: Integer read FOverCostCountInOneTerm write FOverCostCountInOneTerm default 0;
{$IFDEF DEBUG}
property GenCountInOneTerm: Integer read FGenCountInOneTerm write FGenCountInOneTerm default 0;
property TermIndex: Integer read FTermIndex write FTermIndex default 0;
{$ENDIF}
protected
{$IFDEF DEBUG}
procedure DoGenIdAction(arg: TOverCostActionArg);
procedure BeginOverCostAction(UseTimeTick: Int64);
procedure EndOverCostAction(UseTimeTick: Int64);
procedure BeginTurnBackAction(UseTimeTick: Int64);
procedure EndTurnBackAction(UseTimeTick: Int64);
{$ENDIF}
//
function GetSecondTimeStamp(): Int64;
function GetMillisecondTimeStamp(): Int64;
//
function CalcId(UseTimeTick: Int64): Int64; virtual;
function CalcTurnBackId(UseTimeTick: Int64): Int64; virtual;
function NextOverCostId(): Int64;
function GetCurrentTimeTick(): Int64; virtual;
function GetNextTimeTick(): Int64;
public
// Action<OverCostActionArg> GenAction { get; set; }
function NextId(): Int64;
function NextNormalId(): Int64;
constructor Create(options: TIdGeneratorOptions); overload;
destructor Destroy(); override;
end;
implementation
{ TSnowWorkerM1 }
function TSnowWorkerM1.GetSecondTimeStamp(): Int64;
var
ST: TDateTime;
begin
ST := EncodeDateTime(1970, 1, 1, 0, 0, 0, 0);
Result := MilliSecondsBetween(Now(), ST) - 28800; // 8*60*60;
end;
function TSnowWorkerM1.GetMillisecondTimeStamp(): Int64;
var
ST: TDateTime;
begin
ST := EncodeDateTime(1970, 1, 1, 0, 0, 0, 0);
Result := MilliSecondsBetween(Now(), ST) - 28800000; // 8*60*60*1000;
end;
constructor TSnowWorkerM1.Create(options: TIdGeneratorOptions);
begin
SyncLock := TCriticalSection.Create;
// 1.BaseTime
if (options.BaseTime <> 0) then
FBaseTime := options.BaseTime;
// 2.WorkerIdBitLength
if (options.WorkerIdBitLength <> 0) then
begin
FWorkerIdBitLength := 6;
end
else
begin
FWorkerIdBitLength := options.WorkerIdBitLength;
end;
// 3.WorkerId
FWorkerId := options.WorkerId;
// 4.SeqBitLength
if (options.SeqBitLength = 0) then
begin
FSeqBitLength := 6;
end
else
begin
FSeqBitLength := options.SeqBitLength;
end;
// 5.MaxSeqNumber
if (MaxSeqNumber = 0) then
begin
FMaxSeqNumber := (1 shl SeqBitLength) - 1;
end
else
begin
FMaxSeqNumber := options.MaxSeqNumber;
end;
// 6.MinSeqNumber
FMinSeqNumber := options.MinSeqNumber;
// 7.Others
FTopOverCostCount := options.TopOverCostCount;
// if (TopOverCostCount = 0) then
// begin
// FTopOverCostCount := 2000;
// end;
FTimestampShift := Byte(WorkerIdBitLength + SeqBitLength);
FCurrentSeqNumber := options.MinSeqNumber;
// FBaseTimeTick = BaseTime.Ticks;
// FStartTimeTick = (long)(DateTime.UtcNow.Subtract(BaseTime).TotalMilliseconds) - Environment.TickCount;
end;
destructor TSnowWorkerM1.Destroy();
begin
SyncLock.Free;
inherited;
end;
{$IFDEF DEBUG}
procedure TSnowWorkerM1.DoGenIdAction(arg: TOverCostActionArg);
begin
// //return;
// Task.Run(() =>
// {
// GenAction(arg);
// });
end;
procedure TSnowWorkerM1.BeginOverCostAction(UseTimeTick: Int64);
begin
end;
procedure TSnowWorkerM1.EndOverCostAction(UseTimeTick: Int64);
begin
end;
procedure TSnowWorkerM1.BeginTurnBackAction(UseTimeTick: Int64);
begin
end;
procedure TSnowWorkerM1.EndTurnBackAction(UseTimeTick: Int64);
begin
end;
{$ENDIF}
function TSnowWorkerM1.NextOverCostId(): Int64;
var
CurrentTimeTick: Int64;
begin
CurrentTimeTick := GetCurrentTimeTick();
if (CurrentTimeTick > FLastTimeTick) then
begin
{$IFDEF DEBUG}
EndOverCostAction(CurrentTimeTick);
FGenCountInOneTerm := 0;
{$ENDIF}
FLastTimeTick := CurrentTimeTick;
FCurrentSeqNumber := FMinSeqNumber;
FIsOverCost := False;
FOverCostCountInOneTerm := 0;
Result := CalcId(FLastTimeTick);
Exit;
end;
if (FOverCostCountInOneTerm >= FTopOverCostCount) then
begin
{$IFDEF DEBUG}
EndOverCostAction(CurrentTimeTick);
FGenCountInOneTerm := 0;
{$ENDIF}
// TODO: <20><>Ư<EFBFBD><C6AF><EFBFBD><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD>ȴ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ز<EFBFBD><D8B2>ϳ<EFBFBD><CFB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˴<EFBFBD><CBB4><EFBFBD><EFBFBD>ܵȴ<DCB5><C8B4>ϳ<EFBFBD>ʱ<EFBFBD>
// <20><><EFBFBD>Ż<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>Ư<EFBFBD><C6AF><EFBFBD><EFBFBD>ֹʱ<D6B9><CAB1><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ز<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>߼<EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵͣ<CAB5><CDA3>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
FLastTimeTick := GetNextTimeTick();
FCurrentSeqNumber := FMinSeqNumber;
FIsOverCost := False;
FOverCostCountInOneTerm := 0;
Result := CalcId(FLastTimeTick);
Exit;
end;
if (FCurrentSeqNumber > FMaxSeqNumber) then
begin
{$IFDEF DEBUG}
Inc(FGenCountInOneTerm);
{$ENDIF}
Inc(FLastTimeTick);
FCurrentSeqNumber := FMinSeqNumber;
FIsOverCost := True;
Inc(FOverCostCountInOneTerm);
Result := CalcId(FLastTimeTick);
Exit;
end;
{$IFDEF DEBUG}
Inc(FGenCountInOneTerm);
{$ENDIF}
Result := CalcId(FLastTimeTick);
end;
function TSnowWorkerM1.NextNormalId: Int64;
var
CurrentTimeTick: Int64;
begin
CurrentTimeTick := GetCurrentTimeTick();
if (CurrentTimeTick < FLastTimeTick) then
begin
if (FTurnBackTimeTick < 1) then
begin
FTurnBackTimeTick := FLastTimeTick - 1;
Inc(FTurnBackIndex);
// ÿ<><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ5λ<35><CEBB>Ԥ<EFBFBD><D4A4>λ<EFBFBD><CEBB>0<EFBFBD><30><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD>ֵ<EFBFBD><D6B5>1-4<><34>ʱ<EFBFBD><CAB1><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD>
// ֧<><D6A7>4<EFBFBD>λز<CEBB><D8B2><EFBFBD><EFBFBD>򣨱<EFBFBD><F2A3A8B1><EFBFBD><EFBFBD>ز<EFBFBD><D8B2>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>ID<49>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޴λز<CEBB><D8B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD>ʹ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD>
if (FTurnBackIndex > 4) then
begin
FTurnBackIndex := 1;
end;
{$IFDEF DEBUG}
BeginTurnBackAction(FTurnBackTimeTick);
{$ENDIF}
end;
// Sleep(1);
Result := CalcTurnBackId(FTurnBackTimeTick);
Exit;
end;
// ʱ<><CAB1>׷ƽʱ<C6BD><CAB1>_TurnBackTimeTick<63><6B><EFBFBD><EFBFBD>
if (FTurnBackTimeTick > 0) then
begin
{$IFDEF DEBUG}
EndTurnBackAction(FTurnBackTimeTick);
{$ENDIF}
FTurnBackTimeTick := 0;
end;
if (CurrentTimeTick > FLastTimeTick) then
begin
FLastTimeTick := CurrentTimeTick;
FCurrentSeqNumber := FMinSeqNumber;
Result := CalcId(FLastTimeTick);
Exit;
end;
if (FCurrentSeqNumber > FMaxSeqNumber) then
begin
{$IFDEF DEBUG}
BeginOverCostAction(CurrentTimeTick);
Inc(FTermIndex);
FGenCountInOneTerm := 1;
{$ENDIF}
FOverCostCountInOneTerm := 1;
Inc(FLastTimeTick);
FCurrentSeqNumber := FMinSeqNumber;
FIsOverCost := True;
Result := CalcId(FLastTimeTick);
Exit;
end;
Result := CalcId(FLastTimeTick);
end;
function TSnowWorkerM1.CalcId(UseTimeTick: Int64): Int64;
begin
Result := ((UseTimeTick shl FTimestampShift) + (Int64(FWorkerId) shl FSeqBitLength) + Cardinal(FCurrentSeqNumber));
Inc(FCurrentSeqNumber);
end;
function TSnowWorkerM1.CalcTurnBackId(UseTimeTick: Int64): Int64;
begin
Result := ((UseTimeTick shl FTimestampShift) + (Int64(FWorkerId) shl FSeqBitLength) + FTurnBackIndex);
Dec(FTurnBackTimeTick);
end;
function TSnowWorkerM1.GetCurrentTimeTick(): Int64;
var
Millis: Int64;
begin
// Millis := DateTimeToUnix(Now(), False);
Millis := GetMillisecondTimeStamp();
Result := Millis - FBaseTime;
end;
function TSnowWorkerM1.GetNextTimeTick(): Int64;
var
TempTimeTicker: Int64;
begin
TempTimeTicker := GetCurrentTimeTick();
while (TempTimeTicker <= FLastTimeTick) do
begin
// Sleep(1);
TSpinWait.SpinUntil(
function(): Boolean
begin
Result := False;
end, 1);
TempTimeTicker := GetCurrentTimeTick();
end;
Result := TempTimeTicker;
end;
function TSnowWorkerM1.NextId(): Int64;
begin
SyncLock.Enter;
try
if FIsOverCost then
Result := NextOverCostId()
else
Result := NextNormalId();
finally
SyncLock.Leave;
end;
end;
end.

View File

@@ -0,0 +1,75 @@
unit uSnowWorkerM2;
interface
uses System.SysUtils, uSnowWorkerM1, uIdGeneratorOptions, System.SyncObjs;
/// <summary>
/// <20><><EFBFBD><EFBFBD>ѩ<EFBFBD><D1A9><EFBFBD>
/// </summary>
type
TSnowWorkerM2 = class(TSnowWorkerM1)
public
function NextId(): Int64;
constructor Create(options: TIdGeneratorOptions); overload;
end;
implementation
{ TSnowWorkerM2 }
function IncX(var x: Integer): Integer; inline;
begin
Result := x;
Inc(x);
end;
constructor TSnowWorkerM2.Create(options: TIdGeneratorOptions);
begin
inherited Create(options);
end;
function TSnowWorkerM2.NextId(): Int64;
var
CurrentTimeTick: Int64;
begin
SyncLock.Enter;
try
CurrentTimeTick := GetCurrentTimeTick();
if (FLastTimeTick = CurrentTimeTick) then
begin
// if (IncX(FCurrentSeqNumber) > FMaxSeqNumber) then
// begin
// FCurrentSeqNumber := FMinSeqNumber;
// CurrentTimeTick := GetNextTimeTick();
// end;
if ((FCurrentSeqNumber) > FMaxSeqNumber) then
begin
FCurrentSeqNumber := FMinSeqNumber;
CurrentTimeTick := GetNextTimeTick();
end
else
begin
Inc(FCurrentSeqNumber);
end;
end
else
begin
FCurrentSeqNumber := FMinSeqNumber;
end;
if (CurrentTimeTick < FLastTimeTick) then
begin
raise Exception.Create(Format('Time error for %d milliseconds', [FLastTimeTick - CurrentTimeTick]));
end;
FLastTimeTick := CurrentTimeTick;
Result := ((CurrentTimeTick shl FTimestampShift) + (Int64(FWorkerId) shl FSeqBitLength) +
Cardinal(FCurrentSeqNumber));
finally
SyncLock.Leave;
end;
end;
end.

View File

@@ -0,0 +1,91 @@
unit uSnowWorkerM3;
interface
uses System.SysUtils, System.DateUtils, uSnowWorkerM1, uIdGeneratorOptions, System.SyncObjs;
/// <summary>
/// ѩ<><D1A9>Ư<EFBFBD><C6AF><EFBFBD><EFBFBD><E3B7A8>֧<EFBFBD><D6A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ID<49><44><EFBFBD>뼶ʱ<EBBCB6><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
type
TSnowWorkerM3 = class(TSnowWorkerM1)
protected
FDataCenterId: Cardinal;
FDataCenterIdBitLength: Byte;
FTimestampType: Byte;
protected
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ID<49><44>Ĭ<EFBFBD><C4AC>0<EFBFBD><30>
/// </summary>
property DataCenterId: Cardinal read FDataCenterId default 0;
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ID<49><44><EFBFBD>ȣ<EFBFBD>Ĭ<EFBFBD><C4AC>0<EFBFBD><30>
/// </summary>
property DataCenterIdBitLength: Byte read FDataCenterIdBitLength default 0;
/// <summary>
/// ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>0-<2D><><EFBFBD>룬1-<2D><EFBFBD><EBA3A9>Ĭ<EFBFBD><C4AC>0
/// </summary>
property TimestampType: Byte read FTimestampType default 0;
protected
function CalcId(UseTimeTick: Int64): Int64; override;
function CalcTurnBackId(UseTimeTick: Int64): Int64; override;
function GetCurrentTimeTick(): Int64; override;
public
constructor Create(options: TIdGeneratorOptions); overload;
end;
implementation
{ TSnowWorkerM3 }
constructor TSnowWorkerM3.Create(options: TIdGeneratorOptions);
begin
// <20>뼶ʱ<EBBCB6><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
FTimestampType := options.TimestampType;
// DataCenter<65><72><EFBFBD><EFBFBD>
FDataCenterId := options.DataCenterId;
FDataCenterIdBitLength := options.DataCenterIdBitLength;
if (FTimestampType = 1) then
begin
FTopOverCostCount := 0;
end;
FTimestampShift := Byte(DataCenterIdBitLength + WorkerIdBitLength + SeqBitLength);
inherited Create(options);
end;
function TSnowWorkerM3.CalcId(UseTimeTick: Int64): Int64;
begin
Result := ((UseTimeTick shl FTimestampShift) + (Int64(DataCenterId) shl DataCenterIdBitLength) +
(Int64(WorkerId) shl SeqBitLength) + Int64(FCurrentSeqNumber));
Inc(FCurrentSeqNumber);
end;
function TSnowWorkerM3.CalcTurnBackId(UseTimeTick: Int64): Int64;
begin
Result := ((UseTimeTick shl FTimestampShift) + (Int64(DataCenterId) shl DataCenterIdBitLength) +
(Int64(WorkerId) shl SeqBitLength) + FTurnBackIndex);
Dec(FTurnBackTimeTick);
end;
function TSnowWorkerM3.GetCurrentTimeTick: Int64;
var
Millis: Int64;
begin
if (TimestampType = 0) then
begin
Millis := GetMillisecondTimeStamp();
Result := Millis - FBaseTime;
end
else
begin
Millis := GetSecondTimeStamp();
Result := Millis - FBaseTime;
end;
end;
end.