Storing messages received by ServerEventsClient in a database

Hi,

I’ve trying to get my head around storing a message received through a ServerEventsClient into a database.
The application is a CLI/WinForms app, which has a ServerEventsClient running.
The ServerEventsClient is connected to a channel called “Default” and has a NamedReceiver registered for the selector “Default”.

The Receiver has a function “Any” which accepts a message and writes it to the console (for testing).
However, I would like to store the received message into a database managed by the application itself.

How can I access the Receiver or the message being processed?

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var channels = new List<string>
                {
                    "Default"
                };
                var client = new ServerEventsClient("http://localhost:61247", channels.ToArray());
                client.RegisterNamedReceiver<MyReceiver>("Default");
                client.Start();

                Console.WriteLine(client.ConnectionInfo.ToJson());
                Console.WriteLine(client.ReceiverTypes.ToJson());
                Console.WriteLine(client.Status);

                while (true)
                {
                    Thread.Sleep(100);
                    //Console.WriteLine();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                Console.ReadLine();
            }
        }
    }

    public class MyReceiver : ServerEventReceiver
    {
        public void Any(MyMessage request)
        {
            Console.WriteLine("Message received from {0}".Fmt(Client.BaseUri));
            Console.WriteLine(request.Origin);
            Console.WriteLine(request.Destination);
            Console.WriteLine(request.Message);
        }
        public override void NoSuchMethod(string selector, object message) { }
    }
}

The Receiver itself is working fine, I can see the messages being written to the command-line.
However, I cannot find a way to write those to a database, as the Receiver has no knowledge of the database.

What is the best advised way?
Subclassing the Receiver with a reference to a database connection, e.g. through OrmLite?

As I understand, every time a message is received on the channel with that specific selector, a new instance of MyReceiver is created, wouldn’t adding a reference to the Database create tremendous overhead?

Kind regards,
Jan

A new instance is created because ServerEventsClient.Resolver is initialized to use a NewInstanceResolver by default, but you can change it to use a SingletonInstanceResolver strategy which executes it with the same instance with:

client.Resolver = new SingletonInstanceResolver();

But this is a different issue to accessing a database. Like all resources utilizing a connection factory you should be accessing the singleton instance of the factory, one way you can do this is just accessing the same singleton instance in your classes e.g have a static class like:

AppConfig.DbFactory = new OrmLiteConnectionFactory(connString, SqliteDialect.Provider);

Which you can use in your resolvers like:

public class MyReceiver : ServerEventReceiver
{
    public void Any(MyMessage request)
    {
        using (var db = AppConfig.DbFactory.OpenDbConnection())
        {
            db.Insert(request); 
        }
    }
    public override void NoSuchMethod(string selector, object message) { }
}

An alternative is to register it as a dependency that’s injected in your resolvers, e.g:

client.RegisterNamedReceiver<MyReceiver>("Default");

// Register all dependencies used in a new Funq.Container:
var container = new Container();
container.Register<IDbConnectionFactory>(c => 
    new OrmLiteConnectionFactory(connString, SqliteDialect.Provider));

// Go through an auto-wire all Registered Receiver Types with Funq:
container.RegisterAutoWiredTypes(client.ReceiverTypes);

// Change the client to resolve receivers from the new Funq Container:
client.Resolver = container;

Where it will be injected in your classes like:

public class MyReceiver : ServerEventReceiver
{
    public IDbConnectionFactory DbFactory { get; set; }

    public void Any(MyMessage request)
    {
        using (var db = DbFactory.OpenDbConnection())
        {
            db.Insert(request); 
        }
    }
    public override void NoSuchMethod(string selector, object message) { }
}
1 Like

Hi mythz,

Thanks a lot for your reply.
I went to try it right away and it works like a charm.

Cheers,
Jan

1 Like