Using JPL from Spring Boot

I have a project where I load and unload different user files using a Java service that communicates with SWI-Prolog using JPL.
In a typical service request the user wants to load a prolog file, then assert several facts and finally make a query. When the user finishes our service retracts the facts and unloads the file. However, we find that in the next service handling (serviced after the previous one has concluded) the file is still loaded and pollutes the query result.

Can you help to resolve this?

What is the cause?

Thank you

Without details it is hard to tell. Different requests ending up on different threads might be a problem.

That said, if for each query you want to populate Prolog with a program and data, solve that and remove everything you might end up better without JPL, assembling a file, start Prolog, collect the result and be done.

An alternative approach is using in_temporary_module/3 from library(modules). It is a little fragile in the sense that you nicely have to obey its limitations or may end up with a crash. It does provide a means to quickly run a query on a temporarily loaded program without leaving traces. It is used by SWISH for isolating queries. SWISH also uses a dedicated thread for each query.

Isn’t this in principle a “worker”, as found in JavaScript.
Except maybe that it is less isolated. The temporary
modules can use shared libraries?

I always wondered whether below on C level, SWI-Prolog
has not only a concept of Engines, but also a concept of
Knowledgebases? If you have a class Knowledgebase

you can also create a new worker, by first creating a new
knowledge base and then inside this knowledge base a
new engine, to run the worker. But sharing might be limited,

it depends how knowledge bases can be interlinked, maybe
invisible to the end-user, doing some caching tricks.

AFAIK, a worker is a complete instance of the language. A temporary module is merely a Prolog module that can import other modules and you can add clauses to it. Notably no other module may depend on it, i.e., no other module may import from a temporary module. When the goal of in_temporary_module/3 completes, no code may be accessing it. As a result, we can safely discard it.

A cleaner solution would be proper reference counting and GC for predicates and modules. That requires a lot of changes though. So, this is a quick-and-dirty solution to create a temporary isolated space for executing a query on data that is assembled for that query only and can be discarded afterwards. SWISH needed this. The isolation is one-way: the temporary module can use anything, bit nothing outside it can use the temporary module. The limitation is only partially enforced, which makes the thing fragile. Violating this restriction will lead to memory corruption.

Well, there have been a lot of posts and answers hinting it does not. It might actually be quite feasible to implement it. When the system was converted from single threaded to multi-threaded, all previously global variables were split into three structures:

  • Local data (LD in the source) (holding the thread specific data)
  • Global data (GD in the source) (shared data)
  • “Code data”. This concerns some data structures that are initialised at startup and never modified afterwards. They were kept separate because there is no need to think about synchronizing access. C23 might allow us to compute this at compile time and store it away as const data.

So, GD is basically your knowledge base. The abstraction is probably not 100%, but close. As said, actually exploiting this is probably still quite a bit of work. If some project with a need and resources to implement this I’m happy to consider.

The point of my reply is that the “knowledge base” is accessed though a pointer to a struct everywhere. In theory you could create multiple instances of it and add a pointer from the LD thread/engine data to the knowledge base it uses. The required changes could be fairly limited.