JDBC event store and multi-tenancy

Hi,

I have an app that needs to be multi-tenant - ie separate databases altogether for each tenant. Using axon, I’d like to have a separate event store for each tenant. Here’s how I’m planning to approach this - but would help to get some validation/feedback

I have reviewed thread on a similar question here: https://groups.google.com/forum/#!topic/axonframework/GNXJUOXyalY
However, there JPA was used. I’m using a JDBC event store (don’t know much about JPA and don’t think I need the complexity). As usual, the challenge is to be able to switch db connections based on the tenant while reading and writing the eventstream (and managing transactions). I’m also using Spring currently if that is relevant.

Background:

  1. Each tenant has it’s own subdomain - tenA.app.com, tenB.app.com; however, it’s served by a single instance of the application.
  2. When a request comes in to a particular subdomain, a request filter sets an attribute
  3. From the controller when a command is sent, it picks up the tenant Id and includes it in the command.
  4. When a command is dispatched, the tenant Id is included (either in metadata or payload)

Now, in the command handler, the event sourcing repository should point to a different database based on the tenant.

I plan to extract the tenant Id and stick it into a ThreadLocal in the command handler;

Then, set up a jdbc-event-store with a ConnectionProvider that reads the tenant id from the thread local and creates and returns a database connection. Looking at JdbcEventStore and DefaultEventEntryStore, this seems like it should do the trick. A couple of areas where I’m uncomfortable/have doubts

  1. The Unit Of Work wrapper - since I’d provide a connectionprovider directly, it won’t be wrapped in a UoW. What are the implications?

`
public JdbcEventStore(ConnectionProvider connectionProvider) {
this(new DefaultEventEntryStore(connectionProvider), new XStreamSerializer());
}

public JdbcEventStore(DataSource dataSource) {
this(new DefaultEventEntryStore(
new UnitOfWorkAwareConnectionProviderWrapper(new DataSourceConnectionProvider(dataSource))),
new XStreamSerializer()
);
}

`

  1. Implementing ConnectionProvider correctly (transactions) - currently since I use spring, the SpringDataSourceConnectionProvider is used; That automatically picks up a spring txn aware connection; Is it ok to implement a ConnectionProvider that takes a DataSourceProvider which has a getDataSource(tenantId) and have a pretty much identical implementation?

Thanks for reading!
Raghu

After looking around a little bit more - seems like Spring has some support for this in the form of: AbstractRoutingDataSource http://spring.io/blog/2007/01/23/dynamic-datasource-routing/

So instead of dealing with ConnectionProviders, can I just stick in an AbstractRoutingDataSource ?

Thanks!
Raghu

Hi,

Regarding your questions/remarks:
1- The wrapper stores a chosen connection in the unit of work, so the same connection is used for different activities in the same unit of work. It is recommended (although not required) that you use this wrapper, even if you provide your own ConnectionProvider.

2- That seems reasonable. The reason the ConnectionProvider abstract is there, is so that developers can tweak how connections are being created.

Regarding your latest comment:
It’s not so much “instead of ConnectionProviders”, but the AbstractRoutingDataSource could do the trick (haven’t read the details, but it seems to go in the right direction).

Kind regards,

Allard Buijze

Thanks Allard; the AbstractRoutingDataSource worked like a charm. I’ve been digging into the UoW code and it makes a more sense now. However, going with the AbstractRoutingDataSource meant that I don’t have to fiddle with the UoW etc.