Skip to content

Commit

Permalink
Improve samples
Browse files Browse the repository at this point in the history
  • Loading branch information
inputfalken committed Oct 1, 2024
1 parent ff2db50 commit e2c5589
Show file tree
Hide file tree
Showing 7 changed files with 482 additions and 370 deletions.
116 changes: 55 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ Add the following NuGet package as a dependency to your project.
[2]: https://www.nuget.org/packages/Dynatello

## Example
The code is also available in the [samples](samples/) directory.
All examples can be found through the links.

### Extend DTO's
Extend a DTO to contain the mashaller functionality.
[Extend a DTO to contain the mashaller functionality:](samples/ExtendDto)

```csharp
using DynamoDBGenerator.Attributes;
Expand Down Expand Up @@ -52,8 +52,9 @@ public partial record Cat(string Id, string Name, double Cuteness);


### Request middleware
[Every `IRequestHandler<Targ, TResponse>` supports middlewares:](samples/RequestPipeline)


Every `RequestHandler<Targ, TResponse>` supports having multiple middlewares.

```csharp
using System.Diagnostics;
Expand Down Expand Up @@ -107,10 +108,16 @@ public partial record Cat(string Id, string Name, double Cuteness);


### Repository
Isolate DynamoDB code to a repository class.
[Through a repository pattern:](samples/Repository)

```csharp
public class EmployeeRepository
using Amazon.DynamoDBv2;
using Dynatello;
using Dynatello.Builders;
using Dynatello.Builders.Types;
using Dynatello.Handlers;

public partial class EmployeeRepository
{
private readonly IRequestHandler<(string department, string email), Employee?> _getEmployee;
private readonly IRequestHandler<(string department, string email), Employee?> _deleteEmployee;
Expand All @@ -125,40 +132,67 @@ public class EmployeeRepository
Employee?
> _updateLastname;

public EmployeeRepository(string table, IAmazonDynamoDB dynamoDB)
private readonly IAmazonDynamoDB _database;

public EmployeeRepository(IAmazonDynamoDB dynamoDB)
{
_database = dynamoDB;
var middleware = new RequestLogAnalyzer();
_deleteEmployee = Employee
.GetEmployee.OnTable(table)
.GetEmployee.OnTable(TableName)
.ToDeleteRequestHandler(
x => x.ToDeleteRequestBuilder(y => y.department, y => y.email),
x => x.AmazonDynamoDB = dynamoDB
x =>
{
x.AmazonDynamoDB = dynamoDB;
x.RequestsPipelines.Add(middleware);
}
);

_getEmployee = Employee
.GetEmployee.OnTable(table)
.GetEmployee.OnTable(TableName)
.ToGetRequestHandler(
x => x.ToGetRequestBuilder(y => y.department, y => y.email),
x => x.AmazonDynamoDB = dynamoDB
x =>
{
x.AmazonDynamoDB = dynamoDB;
x.RequestsPipelines.Add(middleware);
}
);

_queryByEmail = Employee
.GetByEmail.OnTable(table)
.GetByEmail.OnTable(TableName)
.ToQueryRequestHandler(
x =>
x.WithKeyConditionExpression((x, y) => $"{x.Email} = {y} ")
.ToQueryRequestBuilder() with
{
IndexName = "EmailLookup",
},
x => x.AmazonDynamoDB = dynamoDB
x =>
{
x.AmazonDynamoDB = dynamoDB;
x.RequestsPipelines.Add(middleware);
}
);

_createEmployee = Employee
.Create.OnTable(table)
.ToPutRequestHandler(x => x.ToPutRequestBuilder(), x => x.AmazonDynamoDB = dynamoDB);
.Create.OnTable(TableName)
.ToPutRequestHandler(
x =>
x.WithConditionExpression(
(x, y) => $"{x.Department} <> {y.Department} AND {x.Email} <> {y.Email}"
)
.ToPutRequestBuilder(),
x =>
{
x.AmazonDynamoDB = dynamoDB;
x.RequestsPipelines.Add(middleware);
}
);

_queryByDepartment = Employee
.Query.OnTable(table)
.Query.OnTable(TableName)
.ToQueryRequestHandler(
x =>
x.WithKeyConditionExpression(
Expand All @@ -177,20 +211,22 @@ public class EmployeeRepository
);

_updateLastname = Employee
.UpdateLastname.OnTable(table)
.UpdateLastname.OnTable(TableName)
.ToUpdateRequestHandler(
x =>
x.WithUpdateExpression((x, y) => $"SET {x.LastName} = {y.NewLastname}")
.ToUpdateItemRequestBuilder((x, y) => x.Keys(y.Department, y.Email)) with
{
ReturnValues = ReturnValue.ALL_NEW,
},
x => x.AmazonDynamoDB = dynamoDB
x =>
{
x.AmazonDynamoDB = dynamoDB;
x.RequestsPipelines.Add(middleware);
}
);
}

private static Fixture Fixture = new();

public Task<Employee?> GetPersonById(
string department,
string email,
Expand Down Expand Up @@ -224,47 +260,5 @@ public class EmployeeRepository
string email,
CancellationToken cancellationToken
) => _deleteEmployee.Send((department, email), cancellationToken);

public async Task GenerateEmployeesInDeparment(
string department,
int count,
CancellationToken cancellationToken
)
{
for (var i = 0; i < count; i++)
{
var employee = Fixture.Create<Employee>() with
{
Department = department,
Metadata = new Metadata(DateTime.UtcNow),
};

await _createEmployee.Send(employee, cancellationToken);
}
}
}

[DynamoDBMarshaller(AccessName = "GetByEmail", ArgumentType = typeof(string))]
[DynamoDBMarshaller(
AccessName = "GetEmployee",
ArgumentType = typeof((string department, string email))
)]
[DynamoDBMarshaller(
AccessName = "Query",
ArgumentType = typeof((string Department, string EmailPrefix, DateTime MustBeLessThan))
)]
[DynamoDBMarshaller(AccessName = "Create")]
[DynamoDBMarshaller(
AccessName = "UpdateLastname",
ArgumentType = typeof((string Department, string Email, string NewLastname))
)]
public partial record Employee(
[property: DynamoDBHashKey] string Department,
[property: DynamoDBRangeKey, DynamoDBGlobalSecondaryIndexHashKey("EmailLookup")] string Email,
string LastName,
string[] Skills,
Metadata Metadata
);

public record Metadata(DateTime Timestamp);
```
26 changes: 26 additions & 0 deletions samples/Repository/Employee.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Amazon.DynamoDBv2.DataModel;
using DynamoDBGenerator.Attributes;

[DynamoDBMarshaller(AccessName = "GetByEmail", ArgumentType = typeof(string))]
[DynamoDBMarshaller(
AccessName = "GetEmployee",
ArgumentType = typeof((string department, string email))
)]
[DynamoDBMarshaller(
AccessName = "Query",
ArgumentType = typeof((string Department, string EmailPrefix, DateTime MustBeLessThan))
)]
[DynamoDBMarshaller(AccessName = "Create")]
[DynamoDBMarshaller(
AccessName = "UpdateLastname",
ArgumentType = typeof((string Department, string Email, string NewLastname))
)]
public partial record Employee(
[property: DynamoDBHashKey] string Department,
[property: DynamoDBRangeKey, DynamoDBGlobalSecondaryIndexHashKey("EmailLookup")] string Email,
string LastName,
string[] Skills,
Metadata Metadata
);

public record Metadata(DateTime Timestamp);
150 changes: 150 additions & 0 deletions samples/Repository/EmployeeRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
using Amazon.DynamoDBv2;
using Dynatello;
using Dynatello.Builders;
using Dynatello.Builders.Types;
using Dynatello.Handlers;

public partial class EmployeeRepository
{
private readonly IRequestHandler<(string department, string email), Employee?> _getEmployee;
private readonly IRequestHandler<(string department, string email), Employee?> _deleteEmployee;
private readonly IRequestHandler<string, IReadOnlyList<Employee>> _queryByEmail;
private readonly IRequestHandler<Employee, Employee?> _createEmployee;
private readonly IRequestHandler<
(string Department, string EmailPrefix, DateTime MustBeLessThan),
IReadOnlyList<Employee>
> _queryByDepartment;
private readonly IRequestHandler<
(string Department, string Email, string NewLastname),
Employee?
> _updateLastname;

private readonly IAmazonDynamoDB _database;

public EmployeeRepository(IAmazonDynamoDB dynamoDB)
{
_database = dynamoDB;
var middleware = new RequestLogAnalyzer();
_deleteEmployee = Employee
.GetEmployee.OnTable(TableName)
.ToDeleteRequestHandler(
x => x.ToDeleteRequestBuilder(y => y.department, y => y.email),
x =>
{
x.AmazonDynamoDB = dynamoDB;
x.RequestsPipelines.Add(middleware);
}
);

_getEmployee = Employee
.GetEmployee.OnTable(TableName)
.ToGetRequestHandler(
x => x.ToGetRequestBuilder(y => y.department, y => y.email),
x =>
{
x.AmazonDynamoDB = dynamoDB;
x.RequestsPipelines.Add(middleware);
}
);

_queryByEmail = Employee
.GetByEmail.OnTable(TableName)
.ToQueryRequestHandler(
x =>
x.WithKeyConditionExpression((x, y) => $"{x.Email} = {y} ")
.ToQueryRequestBuilder() with
{
IndexName = "EmailLookup",
},
x =>
{
x.AmazonDynamoDB = dynamoDB;
x.RequestsPipelines.Add(middleware);
}
);

_createEmployee = Employee
.Create.OnTable(TableName)
.ToPutRequestHandler(
x =>
x.WithConditionExpression(
(x, y) => $"{x.Department} <> {y.Department} AND {x.Email} <> {y.Email}"
)
.ToPutRequestBuilder(),
x =>
{
x.AmazonDynamoDB = dynamoDB;
x.RequestsPipelines.Add(middleware);
}
);

_queryByDepartment = Employee
.Query.OnTable(TableName)
.ToQueryRequestHandler(
x =>
x.WithKeyConditionExpression(
(x, y) =>
$"{x.Department} = {y.Department} and begins_with({x.Email}, {y.EmailPrefix})"
)
.WithFilterExpression(
(x, y) => $"{x.Metadata.Timestamp} < {y.MustBeLessThan}"
)
.ToQueryRequestBuilder(),
x =>
{
x.RequestsPipelines.Add(new RequestLogAnalyzer());
x.AmazonDynamoDB = dynamoDB;
}
);

_updateLastname = Employee
.UpdateLastname.OnTable(TableName)
.ToUpdateRequestHandler(
x =>
x.WithUpdateExpression((x, y) => $"SET {x.LastName} = {y.NewLastname}")
.ToUpdateItemRequestBuilder((x, y) => x.Keys(y.Department, y.Email)) with
{
ReturnValues = ReturnValue.ALL_NEW,
},
x =>
{
x.AmazonDynamoDB = dynamoDB;
x.RequestsPipelines.Add(middleware);
}
);
}

public Task<Employee?> GetPersonById(
string department,
string email,
CancellationToken cancellationToken
) => _getEmployee.Send((department, email), cancellationToken);

public Task<IReadOnlyList<Employee>> SearchByEmail(
string email,
CancellationToken cancellationToken
) => _queryByEmail.Send(email, cancellationToken);

public Task<Employee?> CreateEmployee(Employee employee, CancellationToken cancellationToken) =>
_createEmployee.Send(employee, cancellationToken);

public Task<IReadOnlyList<Employee>> QueryByDepartment(
string department,
string emailStartsWith,
DateTime updatedBefore,
CancellationToken cancellationToken
) => _queryByDepartment.Send((department, emailStartsWith, updatedBefore), cancellationToken);

public Task<Employee?> UpdateLastName(
string department,
string email,
string lastname,
CancellationToken cancellationToken
) => _updateLastname.Send((department, email, lastname), cancellationToken);

public Task DeleteEmployee(
string department,
string email,
CancellationToken cancellationToken
) => _deleteEmployee.Send((department, email), cancellationToken);
}
Loading

0 comments on commit e2c5589

Please sign in to comment.