18 changed files with 343 additions and 5 deletions
			
			
		| @ -0,0 +1,19 @@ | ||||
| # Sanhe.Abp.Hangfire.Dashboard | ||||
| 
 | ||||
| Hangfire持久化PostgreSql | ||||
| 
 | ||||
| 
 | ||||
| ## 配置使用 | ||||
| 还需要配置中间件,需要在授权中间件后面。 | ||||
| 
 | ||||
| ```csharp | ||||
| [DependsOn(typeof(AbpHangfireStoragePostgreSqlModule))] | ||||
| public class YouProjectModule : AbpModule | ||||
| { | ||||
| 
 | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ## 注意事项 | ||||
| 
 | ||||
| [作者wwwk] | ||||
| @ -0,0 +1,3 @@ | ||||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||
|   <ConfigureAwait ContinueOnCapturedContext="false" /> | ||||
| </Weavers> | ||||
| @ -0,0 +1,12 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 	<Import Project="..\..\..\configureawait.props" /> | ||||
| 	<Import Project="..\..\..\common.props" /> | ||||
| 
 | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 	</PropertyGroup> | ||||
| 	 | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Volo.Abp.Core" Version="$(VoloAbpVersion)" /> | ||||
| 	</ItemGroup> | ||||
| </Project> | ||||
| @ -0,0 +1,17 @@ | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.DependencyInjection.Extensions; | ||||
| using Sanhe.Abp.IdGenerator.Sanhe.Abp.IdGenerator.Snowflake; | ||||
| using Volo.Abp.Modularity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.IdGenerator.Sanhe.Abp.IdGenerator; | ||||
| 
 | ||||
| public class AbpIdGeneratorModule: AbpModule | ||||
| { | ||||
|     public override void ConfigureServices(ServiceConfigurationContext context) | ||||
|     { | ||||
|         var snowflakeIdOptions = new SnowflakeIdOptions(); | ||||
|         context.Services.ExecutePreConfiguredActions(snowflakeIdOptions); | ||||
| 
 | ||||
|         context.Services.TryAddSingleton<IDistributedIdGenerator>(SnowflakeIdGenerator.Create(snowflakeIdOptions)); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,6 @@ | ||||
| namespace Sanhe.Abp.IdGenerator.Sanhe.Abp.IdGenerator; | ||||
| 
 | ||||
| public interface IDistributedIdGenerator | ||||
| { | ||||
|     long Create(); | ||||
| } | ||||
| @ -0,0 +1,133 @@ | ||||
| using System; | ||||
| using Volo.Abp; | ||||
| 
 | ||||
| namespace Sanhe.Abp.IdGenerator.Sanhe.Abp.IdGenerator.Snowflake; | ||||
| 
 | ||||
| // reference: https://github.com/dotnetcore/CAP | ||||
| // reference: https://blog.csdn.net/lq18050010830/article/details/89845790 | ||||
| public class SnowflakeIdGenerator : IDistributedIdGenerator | ||||
| { | ||||
|     public const long Twepoch = 1288834974657L; | ||||
| 
 | ||||
|     private static readonly object _lock = new object(); | ||||
|     private long _lastTimestamp = -1L; | ||||
| 
 | ||||
|     protected long MaxWorkerId { get; set; } | ||||
|     protected long MaxDatacenterId { get; set; } | ||||
| 
 | ||||
|     protected int WorkerIdShift { get; } | ||||
|     protected int DatacenterIdShift { get; } | ||||
|     protected int TimestampLeftShift { get; } | ||||
|     protected long SequenceMask { get; } | ||||
| 
 | ||||
|     protected SnowflakeIdOptions Options { get; } | ||||
| 
 | ||||
|     private SnowflakeIdGenerator(SnowflakeIdOptions options) | ||||
|     { | ||||
|         Options = options; | ||||
|         WorkerIdShift = options.SequenceBits; | ||||
|         DatacenterIdShift = options.SequenceBits + options.WorkerIdBits; | ||||
|         TimestampLeftShift = options.SequenceBits + options.WorkerIdBits + options.DatacenterIdBits; | ||||
|         SequenceMask = -1L ^ -1L << options.SequenceBits; | ||||
|     } | ||||
| 
 | ||||
|     public static SnowflakeIdGenerator Create(SnowflakeIdOptions options) | ||||
|     { | ||||
|         var idGenerator = new SnowflakeIdGenerator(options) | ||||
|         { | ||||
|             WorkerId = options.WorkerId, | ||||
|             DatacenterId = options.DatacenterId, | ||||
|             Sequence = options.Sequence, | ||||
|             MaxWorkerId = -1L ^ -1L << options.WorkerIdBits, | ||||
|             MaxDatacenterId = -1L ^ -1L << options.DatacenterIdBits | ||||
|         }; | ||||
| 
 | ||||
|         if (idGenerator.WorkerId == 0 || (int)Math.Log10(options.WorkerId) + 1 > idGenerator.MaxWorkerId) | ||||
|         { | ||||
|             if (!int.TryParse(Environment.GetEnvironmentVariable("WORKERID", EnvironmentVariableTarget.Machine), out var workerId)) | ||||
|             { | ||||
|                 workerId = RandomHelper.GetRandom((int)idGenerator.MaxWorkerId); | ||||
|             } | ||||
| 
 | ||||
|             if (workerId > idGenerator.MaxWorkerId || workerId < 0) | ||||
|             { | ||||
|                 throw new ArgumentException($"worker Id can't be greater than {idGenerator.MaxWorkerId} or less than 0"); | ||||
|             } | ||||
| 
 | ||||
|             idGenerator.WorkerId = workerId; | ||||
|         } | ||||
| 
 | ||||
|         if (idGenerator.DatacenterId == 0 || (int)Math.Log10(options.DatacenterId) + 1 > idGenerator.MaxDatacenterId) | ||||
|         { | ||||
|             if (!int.TryParse(Environment.GetEnvironmentVariable("DATACENTERID", EnvironmentVariableTarget.Machine), out var datacenterId)) | ||||
|             { | ||||
|                 datacenterId = RandomHelper.GetRandom((int)idGenerator.MaxDatacenterId); | ||||
|             } | ||||
| 
 | ||||
|             if (datacenterId > idGenerator.MaxDatacenterId || datacenterId < 0) | ||||
|             { | ||||
|                 throw new ArgumentException($"datacenter Id can't be greater than {idGenerator.MaxDatacenterId} or less than 0"); | ||||
|             } | ||||
| 
 | ||||
|             idGenerator.DatacenterId = datacenterId; | ||||
|         } | ||||
| 
 | ||||
|         return idGenerator; | ||||
|     } | ||||
| 
 | ||||
|     public long WorkerId { get; internal set; } | ||||
|     public long DatacenterId { get; internal set; } | ||||
|     public long Sequence { get; internal set; } | ||||
| 
 | ||||
|     public virtual long Create() | ||||
|     { | ||||
|         lock (_lock) | ||||
|         { | ||||
|             var timestamp = TimeGen(); | ||||
| 
 | ||||
|             if (timestamp < _lastTimestamp) | ||||
|             { | ||||
|                 // 如果启用此选项, 发生时间回退时使用上一个时间戳 | ||||
|                 if (!Options.UsePreviousInTimeRollback) | ||||
|                 { | ||||
|                     throw new Exception( | ||||
|                         $"InvalidSystemClock: Clock moved backwards, Refusing to generate id for {_lastTimestamp - timestamp} milliseconds"); | ||||
|                 } | ||||
|                 timestamp = _lastTimestamp; | ||||
|             } | ||||
| 
 | ||||
|             if (_lastTimestamp == timestamp) | ||||
|             { | ||||
|                 Sequence = Sequence + 1 & SequenceMask; | ||||
|                 if (Sequence == 0L) | ||||
|                 { | ||||
|                     timestamp = TilNextMillis(_lastTimestamp); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 Sequence = 0; | ||||
|             } | ||||
| 
 | ||||
|             _lastTimestamp = timestamp; | ||||
|             var id = timestamp - Twepoch << TimestampLeftShift | | ||||
|                      DatacenterId << DatacenterIdShift | | ||||
|                      WorkerId << WorkerIdShift | | ||||
|                      Sequence; | ||||
| 
 | ||||
|             return id; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected virtual long TilNextMillis(long lastTimestamp) | ||||
|     { | ||||
|         var timestamp = TimeGen(); | ||||
|         while (timestamp <= lastTimestamp) timestamp = TimeGen(); | ||||
|         return timestamp; | ||||
|     } | ||||
| 
 | ||||
|     protected virtual long TimeGen() | ||||
|     { | ||||
|         return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,40 @@ | ||||
| namespace Sanhe.Abp.IdGenerator.Sanhe.Abp.IdGenerator.Snowflake; | ||||
| 
 | ||||
| public class SnowflakeIdOptions | ||||
| { | ||||
|     /// <summary> | ||||
|     /// 机器Id | ||||
|     /// </summary> | ||||
|     public int WorkerId { get; set; } | ||||
|     /// <summary> | ||||
|     /// 机器Id长度 | ||||
|     /// </summary> | ||||
|     public int WorkerIdBits { get; set; } | ||||
|     /// <summary> | ||||
|     /// 数据中心Id | ||||
|     /// </summary> | ||||
|     public int DatacenterId { get; set; } | ||||
|     /// <summary> | ||||
|     /// 数据中心Id长度 | ||||
|     /// </summary> | ||||
|     public int DatacenterIdBits { get; set; } | ||||
|     /// <summary> | ||||
|     /// 12bit 的序号 | ||||
|     /// </summary> | ||||
|     public long Sequence { get; set; } | ||||
| 
 | ||||
|     public int SequenceBits { get; set; } | ||||
|     /// <summary> | ||||
|     /// 发生时间回退时使用上一个ID | ||||
|     /// </summary> | ||||
|     public bool UsePreviousInTimeRollback { get; set; } | ||||
| 
 | ||||
|     public SnowflakeIdOptions() | ||||
|     { | ||||
|         WorkerIdBits = 5; | ||||
|         DatacenterIdBits = 5; | ||||
|         Sequence = 0L; | ||||
|         SequenceBits = 12; | ||||
|         UsePreviousInTimeRollback = true; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,3 @@ | ||||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||
|   <ConfigureAwait ContinueOnCapturedContext="false" /> | ||||
| </Weavers> | ||||
| @ -0,0 +1,15 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 
 | ||||
| 	<Import Project="..\..\..\configureawait.props" /> | ||||
| 	<Import Project="..\..\..\common.props" /> | ||||
| 
 | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 	</PropertyGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Volo.Abp.Core" Version="$(VoloAbpVersion)" /> | ||||
| 		<PackageReference Include="Volo.Abp.Settings" Version="$(VoloAbpVersion)" /> | ||||
| 		<PackageReference Include="Volo.Abp.EventBus.Abstractions" Version="$(VoloAbpVersion)" /> | ||||
| 	</ItemGroup> | ||||
| </Project> | ||||
| @ -0,0 +1,9 @@ | ||||
| using Volo.Abp.EventBus.Abstractions; | ||||
| using Volo.Abp.Modularity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.RealTime.Sanhe.Abp.RealTime; | ||||
| 
 | ||||
| [DependsOn(typeof(AbpEventBusAbstractionsModule))] | ||||
| public class AbpRealTimeModule : AbpModule | ||||
| { | ||||
| } | ||||
| @ -0,0 +1,38 @@ | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Sanhe.Abp.RealTime.Localization; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The notification that needs to be localized | ||||
| /// </summary> | ||||
| public class LocalizableStringInfo | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Resource name | ||||
|     /// </summary> | ||||
|     public string ResourceName { get; } | ||||
|     /// <summary> | ||||
|     /// Properties | ||||
|     /// </summary> | ||||
|     public string Name { get; } | ||||
|     /// <summary> | ||||
|     /// Formatted data | ||||
|     /// </summary> | ||||
|     public Dictionary<object, object> Values { get; } | ||||
| 
 | ||||
|     /// <summary> | ||||
|     /// Instantiate <see cref="LocalizableStringInfo"/> | ||||
|     /// </summary> | ||||
|     /// <param name="resourceName">Resource name</param> | ||||
|     /// <param name="name">Properties</param> | ||||
|     /// <param name="values">Formatted data</param> | ||||
|     public LocalizableStringInfo( | ||||
|         string resourceName, | ||||
|         string name, | ||||
|         Dictionary<object, object> values = null) | ||||
|     { | ||||
|         ResourceName = resourceName; | ||||
|         Name = name; | ||||
|         Values = values; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,19 @@ | ||||
| using System; | ||||
| using Volo.Abp.Domain.Entities.Events.Distributed; | ||||
| using Volo.Abp.EventBus; | ||||
| 
 | ||||
| namespace Sanhe.Abp.RealTime.Sanhe.Abp.RealTime; | ||||
| 
 | ||||
| [Serializable] | ||||
| [GenericEventName(Prefix = "abp.realtime.")] | ||||
| public class RealTimeEto<T> : EtoBase | ||||
| { | ||||
|     public T Data { get; set; } | ||||
| 
 | ||||
|     public RealTimeEto() : base() { } | ||||
| 
 | ||||
|     public RealTimeEto(T data) : base() | ||||
|     { | ||||
|         Data = data; | ||||
|     } | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue