Hi Romain,
see my replies embedded below.

Regards.

On 08/01/24 17:43, Romain Manni-Bucau wrote:
Hi Francesco,

Normally if you have one EMF per tenant there is no leak between them since the 
cache instance is stored in the EMF - used that approach in TomEE.

As I am saying below, this is what we have already in Syncope.

My company is also supporting customers heavily using this particular feature: 
it works, I have no issues with that.
Someone is also building a SaaS solution on top of that, so runtime tenant 
addition and removal is also fine.

I am exploring this different approach because it would allow to introduce 
Spring Data JPA, which could have some benefits - see
https://issues.apache.org/jira/browse/SYNCOPE-1799

You can check it in 
org.apache.openjpa.datacache.DataCacheManagerImpl#initialize of each emf which 
should be different.

Thanks for the pointer.

So overall if there is a leak it is likely that it leaks accross transactions 
or some spring cache level.

I think that things are more subtle: consider the following use case.

We have MyEntity with String @Id.

Suppose we have two tenants: A and B.

1. Tenant A will make a REST call which creates a MyEntity instance with key 
"key1" under the db for A.

2. Tenant A will make another REST call which looks for the newly created 
MyEntity instance via:

entityManager.find(MyEntity.class, "key1");

3. Tenant B makes the same call as (1) with the same key "key1": all is fine, a 
new row is created under the db for B.

4. Tenant B makes the same call as (2) with the same key "key1": if not already 
evicted, entityManager will return the MyEntity instance for Tenant A from the cache.

I need to avoid the pitfalls from (4).

Side note: the datasource routing pattern is useless if you have an entity 
manager routing pattern and only use JPA to do database work, both will more 
easily conflict than help.

The idea is not to have an entity manager routing pattern, rather to have a 
cache routing patter on the single entity manager factory; or just to configure 
some predefined partitions.

If you still want to plug the datacase (query cache) configuration in the jpa 
properties can take a custom fully qualified name too.

Le lun. 8 janv. 2024 à 17:14, Francesco Chicchiriccò <ilgro...@apache.org>
a écrit :

Hi there,
at Syncope we have been implementing multi-tenancy by relying on something
like:

* 1 data source per tenant
* 1 entity manager factory per tenant
* 1 transaction manager per tenant
* etc

So far so good.

Now I am experimenting a different approach similar to [1], e.g.

* 1 low-level data source per tenant
* 1 data source extending Spring's AbstractRoutingDataSource using the
value of a ThreadLocal variable as lookup key
* 1 single entity manager factory configured with the routing data source
* 1 single transaction manager
* etc

It mostly works but I am having caching issues with concurrent operations
working on different tenants, so I was wondering: how can I extend the
various OpenJPA (query, data, L1, L2, every one) caches to hold back
different actual instances per tenant and to use the appropriate one
depending on the same ThreadLocal value I have already used above for data
sources?

Thanks in advance.
Regards.

[1] https://github.com/Cepr0/sb-multitenant-db-demo

--
Francesco Chicchiriccò

Tirasa - Open Source Excellence
http://www.tirasa.net/

Member at The Apache Software Foundation
Syncope, Cocoon, Olingo, CXF, OpenJPA, PonyMail
http://home.apache.org/~ilgrosso/

Reply via email to