Coder Social home page Coder Social logo

m-wilczynski / resonance Goto Github PK

View Code? Open in Web Editor NEW
0.0 0.0 0.0 98 KB

๐Ÿ‘จโ€๐Ÿ’ป [C#] Set of libraries that I've used, am using currently or plan to use in a nearby future in similiar or exact way throughout the projects I'm working with.

License: Apache License 2.0

C# 100.00%
architecture clean-architecture distributed-systems oop

resonance's People

Contributors

dependabot[bot] avatar m-wilczynski avatar

Watchers

 avatar  avatar

resonance's Issues

Introduce integration point for common logging libraries

It would be useful to have some sort of IOutboxLogger for implementing integrations with logging libraries for Resonance.Outbox internals (ie. TransactionalOutbox and OutboxForwader functionalities).

Targeted libraries support would be:

  • log4net
  • Serilog
  • NLog

Currently only wrapping around execution of whole mechanism (and IMessageForwarder implementations) is possible.

Enforce dependency on System.Data.SqlClient for Resonance.Outbox.Storage.SqlServer

It seems that .NET Framework based applications would not resolve particular version on System.Data.SqlClient that is required by Dapper in Resonance.Outbox.Storage.SqlServer.

Needs:

  • reproduction in .NET Framework 4.7.x
  • enforcing dependency on System.Data.SqlClient for all platforms (now Dapper pulls it for netstandard2.0 only)
  • some kind of test for both .NET Framework 4.7.x and .NET Core 2.x/3.x?

Add documentation on how to use Outbox

Add documentation on how to use Outbox, ie:

  • send events to ITransactionalOutbox
  • push events out of outbox with IOutboxForwarder with scheduling, using for ex. Hangfire for scheduling and MassTransit for messaging

GetMessagesAsMarkedSent for SQL Server works only because IX for SuccessfulForwardDateUtc is in place

GetMessagesAsMarkedSent for SQL Server:

FROM (SELECT {batchSizeSql} * FROM {_storageConfiguration.SchemaName}.{_storageConfiguration.MessageTableName}) msg

works only because IX for SuccessfulForwardDateUtc is in place::

CREATE NONCLUSTERED INDEX IX_{nameof(SerializedMessage.SuccessfulForwardDateUtc)}

Fix subquery (aliased as msg above), so that it selects batch with TOP X rows only from resultset where SuccessfulForwardDateUtc IS NULL.

Implement ReadThenDelete strategy for Resonance.Outbox.Storage.SqlServer

Currently Resonance.Outbox.Storage.SqlServer implements only ReadThenMarkAsRead strategy.
There is another ReadMode - ReadThenDelete that is currently not implemented for SQL Server storage.

Idea is to DELETE records per batch (or all, depending on ForwardingOptions) and return them to OutboxForwarder with OUTPUT clause.

Implement PostgreSQL integration

Only SQL Server integration is available now via Resonance.Outbox.Storage.SqlServer.
At least one more RDBMS should be available for users to choose, especially if targetting platforms other than Windows.
PostgreSQL looks like a good direction to go.

Point of interest: Npgsql

Introduce sent messages retention policy

If chosen to use ReadMode.ReadThenMarkAsRead strategy, messages table can get out of control pretty quickly.
Some sort of retention policy should be introduced + ways of cleaning sent messages older than X days (hours?).
Should probably be analyzed together with #5.

Introduce forwarding log (journal) retention policy

When #3 is completed, it would be useful to have ability to automatically clean up forwarding log with entries older than X days (hours?).
Provided we have forward from outbox per 3 seconds, it makes (60/3)x60x24 = 28,800/day produced by OutboxForwarder.
If not introduced, log would get quite fat pretty quickly.

Introduce point of integration for non-SQL (no IDbConnection) storage

Problem

Currently both Inbound and Outbound implementation assumes there is:

  • IDbConnection
  • either explicit IDbTransaction or ambient TransactionScope

With such constraints there is no way to introduce other backing storage with NoSQL databases such as MongoDB, Neo4j, Redis etc..

Possible solution

Assuming we want to keep the flow of current Resonance.Outbox API, there should still be a way to:

using (var anyConnection = OpenConnection())
{
    using (var anyTransaction = BeginTransaction())
    {
        anyConnection.DoUserCode();
        outobox.Send(myEvent);
        anyTransaction.Commit();
    }
}

There should be:

  • generic type param for transaction, ie. ITransactionalOutbox<TTransaction> where TTransaction would be any implementation of database transaction, such as:
    • IDbTransaction for SQL Databases
    • AsyncTransaction for Neo4j
    • IClientSession for MongoDb
    • ITransaction for Redis
    • etc.
  • common contract to start connection and transaction and to commit/rollback transaction in IMessageRepository

Such change would change current implementation of these APIs:

ITransactionalOutbox:

public interface ITransactionalOutbox<TTransactionSource>
{
    Task Send<TMessage>(TMessage message, TTransactionSource transaction = null, DateTime? sendTime = null);
}

TransactionalOutbox:

public class SqlTransactionalOutbox : ITransactionalOutbox<IDbTransaction>

IMessageRepository:

public interface IMessageRepository<TTransactionSource>
{
    Task SaveMessage(SerializedMessage serializedMessage, TTransactionSource transaction = null);
    Task<ICollection<SerializedMessage>> GetMessagesAsMarkedSent(TTransactionSource transaction, uint? howManyMessages = null);
    Task<ICollection<SerializedMessage>> GetMessagesAsRemoved(TTransactionSource transaction, uint? howManyMessages = null);
}

SqlServerMessageRepository:

public class SqlServerMessageRepository : IMessageRepository<IDbTransaction>
{
    //(...)
}

and would also introduce extension of contract for IMessageRepository for managing transaction for Outbound part:

public interface IReadMessageRepository<TTransactionSource> : IMessageRepository<TTransactionSource>
{
    Task<TTransactionSource> BeginTransaction();
    Task CommitTransaction();
    Task RollbackTransaction();
}

Definition of done

  1. Implementation of example NoSQL integration; example: MongoDB, Neo4j.
  2. Previous SQL solution still works.

Points of further improvement

Perhaps there also should be a way to introduce transaction options as second generic type param, ie:

public interface IReadMessageRepository<TTransactionSource, TTransactionOptions> : IMessageRepository<TTransactionSource>
{
    Task<TTransactionSource> BeginTransaction(TTransactionOptions transactionOptions);
    //(...)
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.