protected async Task DoWorkAsync(IQueueEntry <SimpleWorkItem> w, AsyncCountdownEvent countdown, WorkInfo info) { _logger.Trace($"Starting: {w.Value.Id}"); Assert.Equal("Hello", w.Value.Data); try { // randomly complete, abandon or blowup. if (RandomData.GetBool()) { _logger.Trace($"Completing: {w.Value.Id}"); await w.CompleteAsync(); info.IncrementCompletedCount(); } else if (RandomData.GetBool()) { _logger.Trace($"Abandoning: {w.Value.Id}"); await w.AbandonAsync(); info.IncrementAbandonCount(); } else { _logger.Trace($"Erroring: {w.Value.Id}"); info.IncrementErrorCount(); throw new Exception(); } } finally { _logger.Trace($"Signal {countdown.CurrentCount}"); countdown.Signal(); } }
private void DoWork(QueueEntry <SimpleWorkItem> w, CountdownEvent latch, WorkInfo info) { Debug.WriteLine("Starting: {0}", w.Value.Id); Assert.Equal("Hello", w.Value.Data); try { // randomly complete, abandon or blowup. if (RandomData.GetBool()) { Debug.WriteLine("Completing: {0}", w.Value.Id); w.Complete(); info.IncrementCompletedCount(); } else if (RandomData.GetBool()) { Debug.WriteLine("Abandoning: {0}", w.Value.Id); w.Abandon(); info.IncrementAbandonCount(); } else { Debug.WriteLine("Erroring: {0}", w.Value.Id); info.IncrementErrorCount(); throw new ApplicationException(); } } finally { latch.Signal(); } }
public SimpleError GenerateSimpleError(int maxErrorNestingLevel = 3, bool generateData = true, int currentNestingLevel = 0) { var error = new SimpleError { Message = @"Generated exception message.", Type = ExceptionTypes.Random() }; if (generateData) { for (int i = 0; i < RandomData.GetInt(1, 5); i++) { string key = RandomData.GetWord(); while (error.Data.ContainsKey(key) || key == Event.KnownDataKeys.Error) { key = RandomData.GetWord(); } error.Data.Add(key, RandomData.GetString()); } } error.StackTrace = RandomData.GetString(); if (currentNestingLevel < maxErrorNestingLevel && RandomData.GetBool()) { error.Inner = GenerateSimpleError(maxErrorNestingLevel, generateData, currentNestingLevel + 1); } return(error); }
private Event CreateSimpleEvent() { var ev = new Event { Date = DateTime.Now, Message = "Testing", Type = Event.KnownTypes.Log, Source = "StorageSerializer" }; if (RandomData.GetBool(80)) { ev.Geo = RandomData.GetCoordinate(); } if (RandomData.GetBool(20)) { ev.Value = RandomData.GetDecimal(); } if (RandomData.GetBool(20)) { ev.Count = RandomData.GetInt(); } if (RandomData.GetBool(80)) { ev.ReferenceId = RandomData.GetAlphaNumericString(0, 10); } return(ev); }
public object GenerateValue(BuilderContext context) { var value = RandomData.GetBool(); return(TypeManager.IsNullableType <bool>(context.CurrentValueGeneratorType) ? (bool?)value : value); }
private static IEnumerable <LocationReader> GenerateLocations() { A.Configure <LocationReader>() .Fill(a => a.Name).AsCity() .Fill(b => b.IsHotel, RandomData.GetBool(80)); return(A.ListOf <LocationReader>(RandomData.GetInt(10, 30))); }
public virtual async Task CanConcurrentlyManageFilesAsync() { await ResetAsync(); var storage = GetStorage(); if (storage == null) { return; } using (storage) { const string queueFolder = "q"; var queueItems = new BlockingCollection <int>(); var info = await storage.GetFileInfoAsync("nope"); Assert.Null(info); await Run.InParallelAsync(10, async i => { var ev = new PostInfo { ApiVersion = 2, CharSet = "utf8", ContentEncoding = "application/json", Data = Encoding.UTF8.GetBytes("{}"), IpAddress = "127.0.0.1", MediaType = "gzip", ProjectId = i.ToString(), UserAgent = "test" }; await storage.SaveObjectAsync(Path.Combine(queueFolder, i + ".json"), ev); queueItems.Add(i); }); Assert.Equal(10, (await storage.GetFileListAsync()).Count()); await Run.InParallelAsync(10, async i => { string path = Path.Combine(queueFolder, queueItems.Random() + ".json"); var eventPost = await storage.GetEventPostAndSetActiveAsync(Path.Combine(queueFolder, RandomData.GetInt(0, 25) + ".json"), _logger); if (eventPost == null) { return; } if (RandomData.GetBool()) { await storage.CompleteEventPostAsync(path, eventPost.ProjectId, SystemClock.UtcNow, true, _logger); } else { await storage.SetNotActiveAsync(path, _logger); } }); } }
private async Task SendEventNoticeAsync(PersistentEvent ev) { ev.Id = TestConstants.EventId; ev.OrganizationId = TestConstants.OrganizationId; ev.ProjectId = TestConstants.ProjectId; ev.StackId = TestConstants.StackId; ev.Date = SystemClock.OffsetUtcNow; await _slackService.SendEventNoticeAsync(ev, _project, RandomData.GetBool(), RandomData.GetBool()); await RunWebHookJobAsync(); }
public async Task MeasureThroughputWithRandomFailures() { var queue = GetQueue(retries: 3, workItemTimeout: TimeSpan.FromSeconds(2), retryDelay: TimeSpan.Zero); if (queue == null) { return; } FlushAll(); using (queue) { await queue.DeleteQueueAsync(); const int workItemCount = 1000; for (int i = 0; i < workItemCount; i++) { await queue.EnqueueAsync(new SimpleWorkItem { Data = "Hello" }); } Assert.Equal(workItemCount, (await queue.GetQueueStatsAsync()).Queued); var metrics = new InMemoryMetricsClient(); var workItem = await queue.DequeueAsync(TimeSpan.Zero); while (workItem != null) { Assert.Equal("Hello", workItem.Value.Data); if (RandomData.GetBool(10)) { await workItem.AbandonAsync(); } else { await workItem.CompleteAsync(); } await metrics.CounterAsync("work"); workItem = await queue.DequeueAsync(TimeSpan.FromMilliseconds(100)); } _logger.Trace((await metrics.GetCounterStatsAsync("work")).ToString()); var stats = await queue.GetQueueStatsAsync(); Assert.True(stats.Dequeued >= workItemCount); Assert.Equal(workItemCount, stats.Completed + stats.Deadletter); Assert.Equal(0, stats.Queued); Trace.WriteLine(CountAllKeys()); } }
private async Task SendEventNoticeAsync(PersistentEvent ev) { var user = UserData.GenerateSampleUser(); var project = ProjectData.GenerateSampleProject(); ev.Id = TestConstants.EventId; ev.OrganizationId = TestConstants.OrganizationId; ev.ProjectId = TestConstants.ProjectId; ev.StackId = TestConstants.StackId; await _mailer.SendEventNoticeAsync(user, ev, project, RandomData.GetBool(), RandomData.GetBool(), 1); await RunMailJobAsync(); }
public virtual void CanConcurrentlyManageFiles() { Reset(); IFileStorage storage = GetStorage(); if (storage == null) { return; } using (storage) { const string queueFolder = "q"; var queueItems = new BlockingCollection <int>(); var info = storage.GetFileInfo("nope"); Assert.Null(info); Parallel.For(0, 10, i => { var ev = new PostInfo { ApiVersion = 2, CharSet = "utf8", ContentEncoding = "application/json", Data = Encoding.UTF8.GetBytes("{}"), IpAddress = "127.0.0.1", MediaType = "gzip", ProjectId = i.ToString(), UserAgent = "test" }; storage.SaveObject(Path.Combine(queueFolder, i + ".json"), ev); queueItems.Add(i); }); Assert.Equal(10, storage.GetFileList().Count()); Parallel.For(0, 10, i => { string path = Path.Combine(queueFolder, queueItems.Random() + ".json"); var eventPost = storage.GetEventPostAndSetActive(Path.Combine(queueFolder, RandomData.GetInt(0, 25) + ".json")); if (eventPost == null) { return; } if (RandomData.GetBool()) { storage.CompleteEventPost(path, eventPost.ProjectId, DateTime.UtcNow, true); } else { storage.SetNotActive(path); } }); } }
protected override Task <JobResult> ProcessQueueEntryAsync(JobQueueEntryContext <PingRequest> context) { RunCount++; _logger.Info(() => $"Got {RunCount.ToOrdinal()} ping. Sending pong!"); if (RandomData.GetBool(1)) { throw new ApplicationException("Boom!"); } return(Task.FromResult(JobResult.Success)); }
protected override async Task <JobResult> ProcessQueueEntryAsync(QueueEntryContext <PingRequest> context) { Interlocked.Increment(ref _runCount); _logger.Info(() => $"Got {RunCount.ToOrdinal()} ping. Sending pong!"); await SystemClock.SleepAsync(TimeSpan.FromMilliseconds(1)).AnyContext(); if (RandomData.GetBool(context.QueueEntry.Value.PercentChanceOfException)) { throw new ApplicationException("Boom!"); } return(JobResult.Success); }
public void MeasureThroughputWithRandomFailures() { var queue = GetQueue(retries: 3, workItemTimeout: TimeSpan.FromSeconds(2), retryDelay: TimeSpan.Zero); if (queue == null) { return; } FlushAll(); using (queue) { queue.DeleteQueue(); const int workItemCount = 10000; for (int i = 0; i < workItemCount; i++) { queue.Enqueue(new SimpleWorkItem { Data = "Hello" }); } Assert.Equal(workItemCount, queue.GetQueueCount()); var metrics = new InMemoryMetricsClient(); var workItem = queue.Dequeue(TimeSpan.Zero); while (workItem != null) { Assert.Equal("Hello", workItem.Value.Data); if (RandomData.GetBool(10)) { workItem.Abandon(); } else { workItem.Complete(); } metrics.Counter("work"); workItem = queue.Dequeue(TimeSpan.FromMilliseconds(100)); } metrics.DisplayStats(); Assert.True(queue.DequeuedCount >= workItemCount); Assert.Equal(workItemCount, queue.CompletedCount + queue.GetDeadletterCount()); Assert.Equal(0, queue.GetQueueCount()); Trace.WriteLine(CountAllKeys()); } }
protected override async Task <JobResult> ProcessQueueEntryAsync(JobQueueEntryContext <PingRequest> context) { RunCount++; Console.WriteLine("Pong!"); if (RandomData.GetBool(80)) { await context.QueueEntry.CompleteAsync().AnyContext(); } else if (RandomData.GetBool(80)) { await context.QueueEntry.AbandonAsync().AnyContext(); } return(JobResult.Success); }
public void CanConcurrentlyManageFiles() { Reset(); IObjectStorage storage = GetStorage(); IJsonSerializer serializer = new DefaultJsonSerializer(); const string queueName = "test"; Parallel.For(0, 25, i => { var ev = new Event { Type = Event.KnownTypes.Log, Message = "test" + i }; storage.Enqueue(queueName, ev); }); Assert.Equal(25, storage.GetObjectList().Count()); var working = new ConcurrentDictionary <string, object>(); Parallel.For(0, 50, i => { var fileBatch = storage.GetEventBatch(queueName, serializer, 2); foreach (var f in fileBatch) { if (working.ContainsKey(f.Item1.Path)) { Debug.WriteLine(f.Item1.Path); } Assert.False(working.ContainsKey(f.Item1.Path)); working.TryAdd(f.Item1.Path, null); } if (RandomData.GetBool()) { object o; foreach (var f in fileBatch) { working.TryRemove(f.Item1.Path, out o); } storage.ReleaseBatch(fileBatch); } else { storage.DeleteBatch(fileBatch); } }); Assert.Equal(25, working.Count + storage.GetQueueFiles(queueName).Count); }
protected override Task <JobResult> ProcessQueueEntryAsync(QueueEntryContext <SampleQueueWorkItem> context) { _metrics.Counter("dequeued"); if (RandomData.GetBool(10)) { _metrics.Counter("errors"); throw new Exception("Boom!"); } if (RandomData.GetBool(10)) { _metrics.Counter("abandoned"); return(Task.FromResult(JobResult.FailedWithMessage("Abandoned"))); } _metrics.Counter("completed"); return(Task.FromResult(JobResult.Success)); }
protected override Task <JobResult> RunInternalAsync(JobContext context) { _metrics.Counter("runs"); if (RandomData.GetBool(10)) { _metrics.Counter("errors"); throw new Exception("Boom!"); } if (RandomData.GetBool(10)) { _metrics.Counter("failed"); return(Task.FromResult(JobResult.FailedWithMessage("Failed"))); } _metrics.Counter("completed"); return(Task.FromResult(JobResult.Success)); }
protected override object MutateGene(PropertyInfo gene, int index, object originalValue, object suggestedRandomValue) { if (NumberHelper.TryGetValue(originalValue, out var value)) { var addValue = (value * ADD_RATE) * (decimal)RandomData.GetDouble(); // something around 10% (ADD_RATE), then a random fraction of it var shouldAdd = RandomData.GetBool(); // add or subtract var result = shouldAdd ? value + addValue : value - addValue; return(_options.IsInRange(result) ? NumberHelper.CastValueToProperType(gene.PropertyType, result) : suggestedRandomValue); } else { return(suggestedRandomValue); } }
internal static Error GenerateError(int maxErrorNestingLevel = 3, bool generateData = true, int currentNestingLevel = 0) { var error = new Error { Message = "Generated exception message.", Type = TestConstants.ExceptionTypes.Random() }; if (RandomData.GetBool()) { error.Code = RandomData.GetInt(-234523453, 98690899).ToString(); } if (generateData) { for (int i = 0; i < RandomData.GetInt(1, 5); i++) { string key = RandomData.GetWord(); while (error.Data.ContainsKey(key) || key == Event.KnownDataKeys.Error) { key = RandomData.GetWord(); } error.Data.Add(key, RandomData.GetWord()); } } var stack = new StackFrameCollection(); for (int i = 0; i < RandomData.GetInt(1, 10); i++) { stack.Add(GenerateStackFrame()); } error.StackTrace = stack; if (currentNestingLevel < maxErrorNestingLevel && RandomData.GetBool()) { error.Inner = GenerateError(maxErrorNestingLevel, generateData, currentNestingLevel + 1); } return(error); }
protected override async Task <JobResult> ProcessQueueEntryAsync(QueueEntryContext <SampleQueueWorkItem> context) { await _metrics.CounterAsync("dequeued").AnyContext(); if (RandomData.GetBool(10)) { await _metrics.CounterAsync("errors").AnyContext(); throw new ApplicationException("Boom!"); } if (RandomData.GetBool(10)) { await _metrics.CounterAsync("abandoned").AnyContext(); return(JobResult.FailedWithMessage("Abandoned")); } await _metrics.CounterAsync("completed").AnyContext(); return(JobResult.Success); }
protected override async Task <JobResult> RunInternalAsync(JobContext context) { await _metrics.CounterAsync("runs").AnyContext(); if (RandomData.GetBool(10)) { await _metrics.CounterAsync("errors").AnyContext(); throw new Exception("Boom!"); } if (RandomData.GetBool(10)) { await _metrics.CounterAsync("failed").AnyContext(); return(JobResult.FailedWithMessage("Failed")); } await _metrics.CounterAsync("completed").AnyContext(); return(JobResult.Success); }
protected override Task <JobResult> ProcessQueueItem(QueueEntry <SampleQueueWorkItem> queueEntry) { _metrics.Counter("dequeued"); if (RandomData.GetBool(10)) { _metrics.Counter("errors"); throw new ApplicationException("Boom!"); } if (RandomData.GetBool(10)) { _metrics.Counter("abandoned"); queueEntry.Abandon(); return(Task.FromResult(JobResult.FailedWithMessage("Abandoned"))); } queueEntry.Complete(); _metrics.Counter("completed"); return(Task.FromResult(JobResult.Success)); }
public async Task CanHandleMultipleWorkItemInstances() { const int workItemCount = 1000; var metrics = new InMemoryMetricsClient(); var queue = new InMemoryQueue <WorkItemData>(retries: 0, retryDelay: TimeSpan.Zero); queue.AttachBehavior(new MetricsQueueBehavior <WorkItemData>(metrics)); var messageBus = new InMemoryMessageBus(); var handlerRegistry = new WorkItemHandlers(); var j1 = new WorkItemJob(queue, messageBus, handlerRegistry); var j2 = new WorkItemJob(queue, messageBus, handlerRegistry); var j3 = new WorkItemJob(queue, messageBus, handlerRegistry); int errors = 0; var jobIds = new ConcurrentDictionary <string, int>(); handlerRegistry.Register <MyWorkItem>(async ctx => { var jobData = ctx.GetData <MyWorkItem>(); Assert.Equal("Test", jobData.SomeData); var jobWorkTotal = jobIds.AddOrUpdate(ctx.JobId, 1, (key, value) => value + 1); Logger.Trace().Message($"Job {ctx.JobId} processing work item #: {jobWorkTotal}").Write(); for (int i = 0; i < 10; i++) { await ctx.ReportProgressAsync(10 * i); } if (RandomData.GetBool(1)) { Interlocked.Increment(ref errors); throw new ApplicationException("Boom!"); } }); for (int i = 0; i < workItemCount; i++) { await queue.EnqueueAsync(new MyWorkItem { SomeData = "Test", Index = i }, true); } var completedItems = new List <string>(); object completedItemsLock = new object(); messageBus.Subscribe <WorkItemStatus>(status => { Logger.Trace().Message($"Progress: {status.Progress}").Write(); if (status.Progress < 100) { return; } lock (completedItemsLock) completedItems.Add(status.WorkItemId); }); var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10)); var tasks = new List <Task> { Task.Run(async() => { await j1.RunUntilEmptyAsync(cancellationTokenSource.Token); cancellationTokenSource.Cancel(); }, cancellationTokenSource.Token), Task.Run(async() => { await j2.RunUntilEmptyAsync(cancellationTokenSource.Token); cancellationTokenSource.Cancel(); }, cancellationTokenSource.Token), Task.Run(async() => { await j3.RunUntilEmptyAsync(cancellationTokenSource.Token); cancellationTokenSource.Cancel(); }, cancellationTokenSource.Token) }; try { await Task.WhenAll(tasks); await Task.Delay(100); } catch (TaskCanceledException) {} Logger.Info().Message($"Completed: {completedItems.Count} Errors: {errors}").Write(); metrics.DisplayStats(_writer); Assert.Equal(workItemCount, completedItems.Count + errors); Assert.Equal(3, jobIds.Count); Assert.Equal(workItemCount, jobIds.Sum(kvp => kvp.Value)); }
public void PopulateEvent(Event ev, bool setUserIdentity = true) { if (MinDate.HasValue || MaxDate.HasValue) { ev.Date = RandomData.GetDateTime(MinDate ?? DateTime.MinValue, MaxDate ?? DateTime.MaxValue); } ev.Type = new[] { Event.KnownTypes.Error, Event.KnownTypes.FeatureUsage, Event.KnownTypes.Log, Event.KnownTypes.NotFound }.Random(); if (ev.Type == Event.KnownTypes.FeatureUsage) { ev.Source = FeatureNames.Random(); } else if (ev.Type == Event.KnownTypes.NotFound) { ev.Source = PageNames.Random(); } else if (ev.Type == Event.KnownTypes.Log) { ev.Source = LogSources.Random(); ev.Message = RandomData.GetString(); string level = LogLevels.Random(); if (!String.IsNullOrEmpty(level)) { ev.Data[Event.KnownDataKeys.Level] = level; } } if (RandomData.GetBool(80)) { ev.Geo = RandomData.GetCoordinate(); } if (RandomData.GetBool(20)) { ev.Value = RandomData.GetInt(0, 10000); } if (setUserIdentity) { ev.SetUserIdentity(Identities.Random()); } ev.SetVersion(RandomData.GetVersion("2.0", "4.0")); ev.AddRequestInfo(new RequestInfo { //ClientIpAddress = ClientIpAddresses.Random(), Path = PageNames.Random() }); ev.Data.Add(Event.KnownDataKeys.EnvironmentInfo, new EnvironmentInfo { IpAddress = MachineIpAddresses.Random() + ", " + MachineIpAddresses.Random(), MachineName = MachineNames.Random() }); for (int i = 0; i < RandomData.GetInt(1, 3); i++) { string key = RandomData.GetWord(); while (ev.Data.ContainsKey(key) || key == Event.KnownDataKeys.Error) { key = RandomData.GetWord(); } ev.Data.Add(key, RandomData.GetString()); } int tagCount = RandomData.GetInt(1, 3); for (int i = 0; i < tagCount; i++) { string tag = EventTags.Random(); if (!ev.Tags.Contains(tag)) { ev.Tags.Add(tag); } } if (ev.Type == Event.KnownTypes.Error) { if (RandomData.GetBool()) { // limit error variation so that stacking will occur if (_randomErrors == null) { _randomErrors = new List <Error>(Enumerable.Range(1, 25).Select(i => GenerateError())); } ev.Data[Event.KnownDataKeys.Error] = _randomErrors.Random(); } else { // limit error variation so that stacking will occur if (_randomSimpleErrors == null) { _randomSimpleErrors = new List <SimpleError>(Enumerable.Range(1, 25).Select(i => GenerateSimpleError())); } ev.Data[Event.KnownDataKeys.SimpleError] = _randomSimpleErrors.Random(); } } }
public async Task CanHandleMultipleWorkItemInstances() { const int workItemCount = 1000; using (var metrics = new InMemoryMetricsClient(new InMemoryMetricsClientOptions { LoggerFactory = Log })) { var options = new InMemoryQueueOptions <WorkItemData> { Retries = 0, RetryDelay = TimeSpan.Zero, LoggerFactory = Log }; using (var queue = new InMemoryQueue <WorkItemData>(options)) { queue.AttachBehavior(new MetricsQueueBehavior <WorkItemData>(metrics, loggerFactory: Log)); using (var messageBus = new InMemoryMessageBus(new InMemoryMessageBusOptions { LoggerFactory = Log })) { var handlerRegistry = new WorkItemHandlers(); var j1 = new WorkItemJob(queue, messageBus, handlerRegistry, Log); var j2 = new WorkItemJob(queue, messageBus, handlerRegistry, Log); var j3 = new WorkItemJob(queue, messageBus, handlerRegistry, Log); int errors = 0; var jobIds = new ConcurrentDictionary <string, int>(); handlerRegistry.Register <MyWorkItem>(async ctx => { var jobData = ctx.GetData <MyWorkItem>(); Assert.Equal("Test", jobData.SomeData); int jobWorkTotal = jobIds.AddOrUpdate(ctx.JobId, 1, (key, value) => value + 1); if (jobData.Index % 100 == 0) { _logger.Trace("Job {jobId} processing work item #: {jobWorkTotal}", ctx.JobId, jobWorkTotal); } for (int i = 0; i < 10; i++) { await ctx.ReportProgressAsync(10 * i); } if (RandomData.GetBool(1)) { Interlocked.Increment(ref errors); throw new Exception("Boom!"); } }); for (int i = 0; i < workItemCount; i++) { await queue.EnqueueAsync(new MyWorkItem { SomeData = "Test", Index = i }, true); } var completedItems = new List <string>(); object completedItemsLock = new object(); await messageBus.SubscribeAsync <WorkItemStatus>(status => { if (status.Progress == 100) { _logger.Trace("Progress: {progress}", status.Progress); } if (status.Progress < 100) { return; } lock (completedItemsLock) completedItems.Add(status.WorkItemId); }); var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10)); var tasks = new List <Task> { Task.Run(async() => { await j1.RunUntilEmptyAsync(cancellationTokenSource.Token); cancellationTokenSource.Cancel(); }, cancellationTokenSource.Token), Task.Run(async() => { await j2.RunUntilEmptyAsync(cancellationTokenSource.Token); cancellationTokenSource.Cancel(); }, cancellationTokenSource.Token), Task.Run(async() => { await j3.RunUntilEmptyAsync(cancellationTokenSource.Token); cancellationTokenSource.Cancel(); }, cancellationTokenSource.Token) }; try { await Task.WhenAll(tasks); } catch (OperationCanceledException ex) { _logger.Error(ex, $"One or more tasks were cancelled: {ex.Message}"); } await SystemClock.SleepAsync(100); _logger.Info("Completed: {completedItems} Errors: {errors}", completedItems.Count, errors); Assert.Equal(workItemCount, completedItems.Count + errors); Assert.Equal(3, jobIds.Count); Assert.Equal(workItemCount, jobIds.Sum(kvp => kvp.Value)); } } } }
/// <summary> /// /// </summary> /// <returns></returns> private MarCard CreateMarCard() { MarCard entity = new MarCard() { CustId = RandomData.GetInt(), //商户Id CardId = Guid.NewGuid().ToString("N"), //卡券ID代表一类卡券 LogoUrl = RandomData.GetString(maxLength: 200), //卡券的商户logo,建议像素为300*300。 CardType = RandomData.GetString(maxLength: 20), //卡券类型(CASH:代金券,DISCOUNT:折扣券,GIFT:兑换券,GROUPON:团购券) CodeType = RandomData.GetString(maxLength: 20), //核销码类型(CODE_TYPE_TEXT文 本 ; "CODE_TYPE_BARCODE"一维码 "CODE_TYPE_QRCODE"二维码 "CODE_TYPE_ONLY_QRCODE",二维码无code显示; "CODE_TYPE_ONLY_BARCODE",一维码无code显示;CODE_TYPE_NONE, 不显示code和条形码类型) Title = RandomData.GetString(maxLength: 30), //卡券名,字数上限为9个汉字。(建议涵盖卡券属性、服务及金额)。 SubTitle = RandomData.GetString(maxLength: 30), //显示在入口下方的提示语 ,仅在卡券状态正常(可以核销)时显示。 Color = RandomData.GetString(maxLength: 16), //券颜色。按色彩规范标注填写Color010-Color100。 Notice = RandomData.GetString(maxLength: 50), //卡券使用提醒,字数上限为16个汉字。 Description = RandomData.GetString(maxLength: 1024), //卡券使用说明,字数上限为1024个汉字。 Quantity = RandomData.GetInt(), //卡券库存的数量,上限为100000000。 DateType = RandomData.GetString(maxLength: 20), //有效期类型(DATE_TYPE_FIX _TIME_RANGE 表示固定日期区间,DATE_TYPE_FIX_TERM表示 X天后生效,X天内有效) DateBeginTime = RandomData.GetDateTime(), //DateType为DATE_TYPE_FIX_TIME_RANGE时专用,表示起用时间 DateEndTime = RandomData.GetDateTime(), //DateType为DATE_TYPE_FIX_TIME_RANGE时专用,表示结束时间 , 建议设置为截止日期的23:59:59过期 DateFixedTerm = RandomData.GetInt(), //DateType为DATE_TYPE_FIX_TERM时专用,表示自领取后多少天内有效,不支持填写0。 DateFixedBeginTerm = RandomData.GetInt(), //DateType为DATE_TYPE_FIX_TERM时专用,表示自领取后多少天开始生效,领取后当天生效填写0。(单位为天) BindOpenid = RandomData.GetBool(), //是否指定用户领取,填写true或false 。默认为false。通常指定特殊用户群体 投放卡券或防止刷券时选择指定用户领取。 ServicePhone = RandomData.GetString(maxLength: 20), //客服电话。 GetLimit = RandomData.GetInt(), //每人可领券的数量限制,不填写默认为50。 UseLimit = RandomData.GetInt(), //每人可核销的数量限制,不填写默认为50。 CanShare = RandomData.GetBool(), //卡券领取页面是否可分享。 CanGiveFriend = RandomData.GetBool(), //卡券是否可转赠 AcceptCategory = RandomData.GetString(), //指定可用的商品类目 RejectCategory = RandomData.GetString(), //指定不可用的商品类目,仅用于代金券类型 ,填入后将在券面拼写不适用于xxxx AcceptProduct = RandomData.GetString(), //指定可用的商品 RejecProduct = RandomData.GetString(), //指定不可用的商品 ReduceCost = RandomData.GetDecimal(0, (int)Math.Pow(2, 6)), //代金券专用,表示减免金额 LeastCost = RandomData.GetDecimal(0, (int)Math.Pow(2, 6)), //满减门槛字段,可用于兑换券和代金券 ,填入后将在全面拼写消费满xx元可用。 Discount = RandomData.GetDecimal(0, (int)Math.Pow(2, 6)), //折扣券专用,表示打折额度(百分比) CanUseWithOtheDiscount = RandomData.GetBool(), //不可以与其他类型共享门槛 ,填写false时系统将在使用须知里 拼写“不可与其他优惠共享”, 填写true时系统将在使用须知里 拼写“可与其他优惠共享”, 默认为true BusinessService = RandomData.GetString(maxLength: 200), //Arry类型 商家服务类型: BIZ_SERVICE_DELIVER 外卖服务; BIZ_SERVICE_FREE_PARK 停车位; BIZ_SERVICE_WITH_PET 可带宠物; BIZ_SERVICE_FREE_WIFI 免费wifi, 可多选 /* * { * type 否 string(24 ) 限制类型枚举值:支持填入 MONDAY 周一 TUESDAY 周二 WEDNESDAY 周三 THURSDAY 周四 FRIDAY 周五 SATURDAY 周六 SUNDAY 周日 此处只控制显示, 不控制实际使用逻辑,不填默认不显示 * begin_hour 否 int 当前type类型下的起始时间(小时) ,如当前结构体内填写了MONDAY, 此处填写了10,则此处表示周一 10:00可用 * begin_minute 否 int 当前type类型下的起始时间(分钟) ,如当前结构体内填写了MONDAY, begin_hour填写10,此处填写了59, 则此处表示周一 10:59可用 * end_hour 否 int 当前type类型下的结束时间(小时) ,如当前结构体内填写了MONDAY, 此处填写了20, 则此处表示周一 10:00 - 20:00可用 * end_minute 否 int 当前type类型下的结束时间(分钟) ,如当前结构体内填写了MONDAY, begin_hour填写10,此处填写了59, 则此处表示周一 10:59 - 00:59可用 * } */ TimeLimit = @"[{""type"": ""MONDAY"", ""begin_hour"": 0,""end_hour"": 10,""begin_minute"": 10,""end_minute"": 59 }]", //JSON结构 使用时段限制,包含以下字段 AbstractIntro = RandomData.GetString(maxLength: 24), //封面摘要简介 AbstractIconUrlList = RandomData.GetString(maxLength: 200), //封面图片列表,仅支持填入一 个封面图片链接, 上传图片接口 上传获取图片获得链接,填写 非CDN链接会报错,并在此填入。 建议图片尺寸像素850*350 ConsumeType = default(byte?), //核销方式(1:自助买单,2:自助核销,3:用扫码核销--二维码_条形码_仅卡券号) ConsumeNeedVerifyCode = RandomData.GetBool(), //自助核销是否启用验证码(消费者持券到店,须输入验证码才能核销卡券) ConsumeVerifyCode = RandomData.GetString(maxLength: 3), //自助核销验证码(消费者持券到店,须输入验证码才能核销卡券) ConsumeNeedRemarkAmount = RandomData.GetBool(), //自助核销是否启用备注交易金额(商户选择备注交易金额后,用户持券到店,须备注本次交易的金额才能成功销券,用于对账。) BranchNo = RandomData.GetString(), //适应的门店编号如:1234,5678 Status = default(byte), //卡券状态(0:待审核,1:审核中,2:审核通过(待投放),3:审核未通过,4:已投放,5:下架) SendNum = RandomData.GetInt(), //投放数量 UseNum = RandomData.GetInt(), //核销数量 QuantityThreshold = RandomData.GetInt(), //库存阈值(当库存少于X提醒) QuantityThresholdNotificCount = RandomData.GetInt(), //库存阈值提醒次数 QuantityThresholdNotificStatus = default(byte), //库存阈值提醒状态(0:禁用,1:启用) CreateTime = DateTime.Now, //创建时间 CreateUser = RandomData.GetInt(), //创建用户 UpdateTime = RandomData.GetDateTime(), //修改时间 UpdateUser = RandomData.GetInt(), //修改用户 DeleteFlag = false, //删除标志 1删除 DeleteUser = RandomData.GetInt(), //删除用户 DeleteTime = RandomData.GetDateTime(), //删除时间 }; return(entity); }
protected override T ChooseGeneGiver(PropertyInfo gene, int index, T parentA, T parentB) { return(RandomData.GetBool() ? parentA : parentB); }