Safe and correct way to execute a listing or predicates in the PEngines temporary module?

I’m using: SWI-Prolog version 8.0.2 on Ubuntu Linux 18.04.

I want my PEngines code to have the following control flow:

  • NodeJS: Get the user’s Prolog user_data() predicates from a standard database (done).
  • CREATE PENGINES INSTANCE: Append the src_text parameter during the PEngines create call with this data (done). This restores the user data created from the last Prolog query (i.e. - it restores the user’s state).
  • Execute the current query, which will almost always execute a number of assert/retract operations to a predicate named user_data(). As I understand it, these operations will only affect a temporary database private to the PEngines thread and that temporary database will be deleted once the PEngines instance is destroyed. (Done).
  • Execute a listing(user_data(_)) query to get the updated state of the user_data() database predicate. (Can’t do, getting a sandbox permission error)
  • NodeJS: Save the user_data() predicate listing from the previous step to the standard database. (Done).
  • DESTROY PENGINES INSTANCE: Destroy the PEngines instance now that the current transaction with the user is over. (Done.)

I put the listing(user_data()) in a dedicated predicate found in the code I pass in the src_text parameter:

list_user_data :-
    listing(user_data(_)).

As stated above, I can’t execute the list_user_data/0 call from a PEngines query using ask() because I get a sandbox error.

No permission to call sandboxed 
`'$current_module'(_1006,_1008)'
Reachable from:
  '$syspreds':current_module(A)
  '$syspreds':generate_current_predicate(A,B,C:D)
  prolog_listing:current_predicate(A,B:C)
  prolog_listing:list_module(A,B)
  prolog_listing:listing_('d146eeb7-f2cf-42c7-8f3e-acd9a882e022':A,B)
  prolog_listing:listing('d146eeb7-f2cf-42c7-8f3e-acd9a882e022':A,B)
  'd146eeb7-f2cf-42c7-8f3e-acd9a882e022':listing(A)
  'd146eeb7-f2cf-42c7-8f3e-acd9a882e022':list_user_data

I was going to move list_user_data/0 to the main server thread to the code loaded at startup, and then mark that predicate as safe with safe_primitive/1, but I am worried that it might list user_data() predicates belonging to the a database on another thread (i.e. - list the wrong user’s data). I am also worried that it might list user_data(_) predicates that are in the main database on the main server thread since there are a few user_data() facts lying around from a few server startup tests that are run when I launch the server.

What is the best and safest way for me to get the list of the user_data() predicates stored in the temporary database for the PEngines instance I am currently using?

Just call user_data(X) from the client? If X are complex terms and you want them as strings, add

user_data_string(S) :-
    user_data(D),
    term_string(D, S).
1 Like

So is this a case where I use the chunking parameter with the ask() method to do an ad hoc findall(), so that you get all the solutions for user_data(X) in an efficient manner? That is a suggestion you made to me on another thread.