We have two Elixir applications, I'll call them P and C. Conceptually C depends on P.
When a particular new record is created by the P application, it sends out a broadcast message within the Elixir ecosystem (using Swarm, but that detail shouldn't be important). A process in the C application listens for that broadcast and creates an additional record in its repo that is specific to its application's purposes.
In production, this seems to work fine, but it is wreaking havoc on our ExUnit tests, even though I've configured shared ownership of the repos in question.
What I think is happening is roughly this:
- The lifetime of any given tests that causes something to happen in P is definite and clearly wraps up in time.
- However, the side-effects of the action in P cause database trigger an action in the C repo that is likely to occur after the test's lifetime has expired. This is essentially a race condition on the expiration of the test and thus the expiration of the ownership.
- It's not really reasonable to have tests wait for the side effect in C because most tests aren't testing that.
There are two alternative architectures for this problem that I've considered, both of which have (IMHO) downsides:
- Reverse the dependency, then P can call C and tell it (synchronously) to build the appropriate message. (Downside: This dependency is conceptually wrong.)
- Build some sort of configuration mechanism by which P can call a behaviour synchronously; C can then register itself with this mechanism and use that to build the message. (Downside: How to register the behaviour module ID in a world with immutable data?)
Of the two, I definitely prefer #2, but I haven't figured out how to implement it reliably.
Any advice? Any approaches I should consider, but haven't listed?
Thanks much …