> dotnet new console --name TaskManager.Service dotnet new webapi --name TaskManager.Apicd TaskManager.Api
dotnet add package Cronus
cd ../TaskManager.Service
dotnet add package Cronus
dotnet add package Cronus.Transport.RabbitMQ
dotnet add package Cronus.Persistence.Cassandra
dotnet add package Cronus.Serialization.NewtonsoftJson
dotnet add package Microsoft.Extensions.Hosting "Persistence": { /* ... */ },
"Projections": {
"Cassandra": {
"ConnectionString": "Contact Points=127.0.0.1;Port=9042;Default Keyspace=taskmanager_projections"
}
}dotnet add package Cronus.Projection.Cassandra

[DataContract(Name = "c94513d1-e5ee-4aae-8c0f-6e85b63a4e03")]
public class TaskProjection : ProjectionDefinition<TaskProjectionData, TaskId>,
IEventHandler<TaskCreated>
{
public TaskProjection()
{
//Id.NID - here we are subscribing by tenant
//in our case the tenant is: "tenant"
//so we well get all events
Subscribe<TaskCreated>(x => new TaskId(x.Id.NID));
}
public Task HandleAsync(TaskCreated @event)
{
Data task = new Data();
task.Id = @event.Id;
task.UserId = @event.UserId;
task.Name = @event.Name;
task.Timestamp = @event.Timestamp;
State.Tasks.Add(task);
return Task.CompletedTask;
}
public IEnumerable<Data> GetTaskByName(string name)
{
return State.Tasks.Where(x => x.Name.Equals(name));
}
}{
"Cronus": {
"BoundedContext": "taskmanager",
"Tenants": [ "tenant" ],
"Transport": {
"RabbitMQ": {
"Server": "127.0.0.1",
"VHost": "taskmanager"
},
"PublicRabbitMQ": [
{
"Server": "127.0.0.1",
"VHost": "unicom-public",
"FederatedExchange": {
"UpstreamUri": "guest:guest@localhost:5672",
"VHost": "unicom-public",
"UseSsl": false,
"MaxHops": 1
}
}
]
},
"Persistence": {
"Cassandra": {
"ConnectionString": "Contact Points=127.0.0.1;Port=9042;Default Keyspace=taskmanager_es"
}
},
"Projections": {
"Cassandra": {
"ConnectionString": "Contact Points=127.0.0.1;Port=9042;Default Keyspace=taskmanager_projections"
}
},
"Cluster": {
"Consul": {
"Address": "127.0.0.1"
}
},
"AtomicAction": {
"Redis": {
"ConnectionString": "127.0.0.1:6379"
}
}
}
}using Cronus11Service;
using Elders.Cronus;
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
services.AddCronus(hostContext.Configuration);
})
.UseDefaultServiceProvider((context, options) =>
{
options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
options.ValidateScopes = false;
options.ValidateOnBuild = false;
})
.Build();
host.Run();builder.Services.AddCronus(builder.Configuration);
builder.Host.UseDefaultServiceProvider((context, options) =>
{
options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
options.ValidateScopes = false;
options.ValidateOnBuild = false;
}
);
....
app.UseCronusAspNetCore();
[DataContract(Name = "c135893e-b9e3-453a-b0e0-53545094ec5d")]
public class TaskProjectionData
{
public TaskProjectionData()
{
Tasks = new List<Data>();
}
[DataMember(Order = 1)]
public List<Data> Tasks { get; set; }
[DataContract(Name = "317b3cbb-593a-4ffc-8284-d5f5c599d8ae")]
public class Data
{
[DataMember(Order = 1)]
public TaskId Id { get; set; }
[DataMember(Order = 2)]
public UserId UserId { get; set; }
[DataMember(Order = 3)]
public string Name { get; set; }
[DataMember(Order = 4)]
public DateTimeOffset CreatedAt { get; set; }
[DataMember(Order = 5)]
public DateTimeOffset Timestamp { get; set; }
}
}[ApiController]
[Route("[controller]/[action]")]
public class TaskController : ControllerBase
{
private readonly IPublisher<CreateTask> _publisher;
private readonly IProjectionReader _projectionReader;
public TaskController(IPublisher<CreateTask> publisher, IProjectionReader reader)
{
_publisher = publisher;
_projectionReader = reader;
}
//.... create task code ..//
[HttpGet]
public async Task<IActionResult> GetTasksByName(string name)
{
ReadResult<TaskProjection> readResult = await _projectionReader.GetAsync<TaskProjection>(new TaskId("tenant"));
if (readResult.IsSuccess == false)
return NotFound();
var TasksByName = readResult.Data.GetTaskByName(name);
return Ok(TasksByName);
////Get all tasks
//return Ok(readResult.Data.State.Tasks.Select(x => new TaskData
//{
// CreatedAt = x.CreatedAt,
// Id = x.Id,
// Name = x.Name,
// Timestamp = x.Timestamp,
// UserId = x.UserId
//}));
}protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
logger.LogInformation("Starting service...");
cronusHost.Start();
// Dashboard configuration
cronusDashboard = CronusApi.GetHost();
cronusApi.Provider = cronusDashboard.Services;
await cronusDashboard.StartAsync().ConfigureAwait(false);
logger.LogInformation("Service started!");
}

[DataContract(Name = "857d960c-4b91-49cc-98fd-fa543906c52d")]
public class CreateTask : ICommand
{
public CreateTask() { }
public CreateTask(TaskId id, UserId userId, string name, DateTimeOffset timestamp
{
if (id is null) throw new ArgumentNullException(nameof(id));
if (userId is null) throw new ArgumentNullException(nameof(userId));
if (name is null) throw new ArgumentNullException(nameof(name));
if (timestamp == default) throw new ArgumentNullException(nameof(timestamp));
Id = id;
UserId = userId;
Name = name;
Timestamp = timestamp;
}
[DataMember(Order = 1)]
public TaskId Id { get; private set; }
[DataMember(Order = 2)]
public UserId UserId { get; private set; }
[DataMember(Order = 3)]
public string Name { get; private set; }
[DataMember(Order = 4)]
public DateTimeOffset Timestamp { get; private set; }
public override string ToString()
{
return $"Create a task with id '{Id}' and name '{Name}' for user [{UserId}].";
}
}[DataContract(Name = "728fc4e7-628b-4962-bd68-97c98aa05694")]
public class TaskCreated : IEvent
{
TaskCreated() { }
public TaskCreated(TaskId id, UserId userId, string name, DateTimeOffset timestamp)
{
Id = id;
UserId = userId;
Name = name;
CreatedAt = DateTimeOffset.UtcNow;
Timestamp = timestamp;
}
[DataMember(Order = 1)]
public TaskId Id { get; private set; }
[DataMember(Order = 2)]
public UserId UserId { get; private set; }
[DataMember(Order = 3)]
public string Name { get; private set; }
[DataMember(Order = 4)]
public DateTimeOffset CreatedAt { get; private set; }
[DataMember(Order = 5)]
public DateTimeOffset Timestamp { get; private set; }
public override string ToString()
{
return $"Task with id '{Id}' and name '{Name}' for user [{UserId}] at {CreatedAt} has been created.";
}
}public class TaskAggregate : AggregateRoot<TaskState>
{
public TaskAggregate() { }
public void CreateTask(TaskId id, UserId userId, string name, DateTimeOffset deadline)
{
IEvent @event = new TaskCreated(id, userId, name, deadline);
Apply(@event);
}
}public class TaskState : AggregateRootState<TaskAggregate, TaskId>
{
public override TaskId Id { get; set; }
public UserId UserId { get; set; }
public string Name { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public DateTimeOffset Deadline { get; set; }
public void When(TaskCreated @event)
{
Id = @event.Id;
UserId = @event.UserId;
Name = @event.Name;
CreatedAt = @event.CreatedAt;
Deadline = @event.Timestamp;
}
}[DataContract(Name = "ef669879-5d35-4cb7-baea-39a7c46c9e13")]
public class TaskService : ApplicationService<TaskAggregate>,
ICommandHandler<CreateTask>
{
public TaskService(IAggregateRepository repository) : base(repository) { }
public async Task HandleAsync(CreateTask command)
{
ReadResult<TaskAggregate> taskResult = await repository.LoadAsync<TaskAggregate>(command.Id).ConfigureAwait(false);
if (taskResult.NotFound)
{
var task = new TaskAggregate();
task.CreateTask(command.Id, command.UserId, command.Name, DateTimeOffset.UtcNow);
await repository.SaveAsync(task).ConfigureAwait(false);
}
}
}[ApiController]
[Route("[controller]/[action]")]
public class TaskController : ControllerBase
{
private readonly IPublisher<ICommand> _publisher;
public TaskController(IPublisher<ICommand> publisher)
{
_publisher = publisher;
}
[HttpPost]
public IActionResult CreateTask(CreateTaskRequest request)
{
string id = Guid.NewGuid().ToString();
string Userid = Guid.NewGuid().ToString();
TaskId taskId = new TaskId(id);
UserId userId = new UserId(Userid);
var expireDate = DateTimeOffset.UtcNow;
expireDate.AddDays(request.DaysActive);
CreateTask command = new CreateTask(taskId, userId, request.Name, expireDate);
if (_publisher.Publish(command) == false)
{
return Problem($"Unable to publish command. {command.Id}: {command.Name}");
};
return Ok(id);
}
}public class CreateTaskRequest
{
[Required]
public string Name { get; set; }
[Required]
public int DaysActive { get; set; }
}