I’ve successfully prototyped a multi-tenant flowable 6.8.0 spring boot app that has a shared process engine and a database-per-tenant setup. I haven’t tried registering tenants at runtime yet, which is one of my requirements, but the Multi Schema Process Engine Configuration has an approach for this that I can try later. At this point, I’m trying to add an event registry engine so that I can initiate workflows via the message broker and also implement triggerable service tasks to delegate task workloads out to other services via the same broker. This is where I’m running into conceptual problems and I’d appreciate any advice.
My first approach was to have the event registry engine share the same multi-tenant datasource as the process engine. I had some success with this by:
Iterating known tenants at boot time and creating the event registry’s schema for each tenant, in similar fashion as the MultiSchemaMultiTenantProcessEngineConfiguration.
adding an event registry event consumer to the process engine that picks up the tenant id from an incoming event and applies it to the tenant context.
The problem I couldn’t figure out with this approach was what to do with the ChannelDefinitionQueryImpl command that executes at bootup after all the engines have been created. It appears to be querying the known inbound channel definitions so that it can configure consumers to the message broker. At bootup, there is no tenant context, and if I declare a dummy tenant, I would only have that tenant’s channels initialized.
My second approach was to “pin” the event registry engine to a “default” tenant so that the event and channel deployments for all tenants provision into that “default” tenant’s schema. Of course the problem here is that for a given (inbound or outbound) event, the thread can bounce back and forth between the event registry engine and the process engine. I tried managing this with command interceptors that kept track of the appropriate tenant at a given point in the stack, either “default” for event registry commands, or “actual” for process engine commands. The problem with this is that there are many times where the current command does not ask the TenantAwareDataSource for a connection, as it will simply share whatever happens to be in the transaction context, and so whatever happens to be in the TenantInfoHolder is irrelevant.
My guess is that the first approach is the most viable of the two, but what do you suggest? And if I go with the first approach, how should the event registry be initialized given that there will be channel definitions in all the various tenants? Should I just iterate the tenants and issue the ChannelDefinitionQueryImpl command?
Up to now we haven’t really received any requests for a Multi Schema Event Registry engine.
Regarding the call that is done during bootup, this can be disabled by setting the enableEventRegistryChangeDetectionAfterEngineCreate property on the EventRegistryEngineConfiguration to false. Once you have that you can fully control how you want to initialise the deployed channel definitions. The idea of that call during bootup is to deploy the latest versions of the channels. I would run that deploy call for each available tenant. In addition to that you might be able to achieve this by registering a custom multi tenant aware EventRegistryChangeDetectionExecutor (similar like the async executor).
Thanks @filiphr . I did feel like I was exploring new territory, so thanks for confirming this. I don’t necessarily need a multi schema event registry, but I do need a multi schema process engine, and it seems the only viable way to integrate the two is to have them both on the same tenant aware data source. I will attempt the enableEventRegistryChangeDetectionAfterEngineCreate approach and report back.
Setting the flag to false had no effect, as I am using the spring boot starters and therefore the SpringEventRegistryEngineConfiguration. The spring implementation already sets the flag to false in its constructor and then unconditionally initializes the channel definitions in its Lifecyle.start() method.
I just discovered multi-schema tenancy is not supported in Spring Boot. Is it the auto-configuration in flowable’s spring boot starters that makes this incompatible? Would you recommend that I move away from the starter dependencies and create the process and event registry engines manually to achieve multi-schema tenancy?
If you know what you are doing you might be able to make the multi schema work with our starters. However, you need to expose the MultiSchema Process Engine configuration as a bean anyways. Perhaps an approach like that for the event registry would work as well. I believe that a custom event registry engine configuration would be the only way to go around the Lifecycle#start method that boots up the check.
Your comment about no requests for a Multi Schema Event Registry gave me an idea to try, which is to declare @Beans for the Multi Schema Process Engine and Configuration using a Tenant Aware Data Source, but allowing auto configuration to build the Event Registry Engine and App Engine with a common @Primary Data Source that keeps all tenants in the same schema. I tried this because my only requirement is to have physical data separation of customer data which I expect to persist in ACT_RU_VARIABLE and ACT_HI_VARINST. The event registry, however, should not have customer data to my knowledge, so it does not require data separation.
I was able to boot with this configuration. As I hoped, the Process Engine tables were created in the tenant-specific schemas, and the Event Registry tables in the common, primary schema. This looked really promising. However, when the Event Registry received a message off the message queue, it wasn’t able to find any subscribers, presumably because it queried ACT_RU_EVENT_SUBSCR in the common, primary schema rather than the tenant-specific schemas where the subscribers actually live.
Based on this, it looks like my Process Engine and Event Registry are required to share the same tenant aware data source. Would you agree that is truly a requirement?