# Need clarifications on PEngines temporary module?

**URL:** <https://swi-prolog.discourse.group/t/need-clarifications-on-pengines-temporary-module/760>\
**Category:** Help!\
**Created:** [June 3, 2019, 1:54pm UTC](https://swi-prolog.discourse.group/t/need-clarifications-on-pengines-temporary-module/760 "2019-06-03T13:54:53Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![prodog](https://avatars.discourse-cdn.com/v4/letter/p/57b2e6/32.png) [@prodog](https://swi-prolog.discourse.group/u/prodog)\
**Post date:** [June 3, 2019, 1:54pm UTC](https://swi-prolog.discourse.group/t/need-clarifications-on-pengines-temporary-module/760/1 "2019-06-03T13:54:53Z")

</div>

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

In this message I thought I learned that any facts asserted during a query to a PEngines instance were volatile and did not persist beyond the current query:

> [@How to stop Pengine self-destruction? (destruct parameter is False)](https://swi-prolog.discourse.group/t/how-to-stop-pengine-self-destruction-destruct-parameter-is-false/739/6):
>
> Yes, a Pengine is a thread that operates on a temporary module. That it where it loads src\_text. If you assert, data goes there too, so other Pengines do not see your data. Creation is indeed quite cheap, mostly depending how much source code you load into it. If you want to share data or preserve data longer than the Pengine lives you need to load code into the server that is accessible from the pengine application and manages this data. You must declare this API as safe and you must mak…

However, in my code base I just ran a quick test. In the first step I made a query to my PEngines database that did an assertion. In my second query, I checked to see if the fact asserted in the first query was still there and to my surprise it was. Somewhere my understanding is wrong and I need to refine it.

Initial query to get current player location:

```prolog
Attempting Prolog query: pengine_execute_single_user_action(get_player_location(PlayerLocation),QueryReport)
Query succeeded. Current solution.
[{"PlayerLocation":"anteroom","QueryReport":["empty_report"]}]
BETTER JSON OBJ: 
{
    "PlayerLocation": "anteroom",
    "QueryReport": "empty_report"
}
No more solutions
Client side Pengine instance successfully destroyed.
Object received:{
    "event": "destroy",
    "id": "78f4b0d6-4008-4ab3-bd73-0c0db5842ee9",
    "pengine": {
        "options": {
            "server": "http://localhost:3030/pengine",
            "application": "tsll",
            "destroy": false,
            "format": "json"
        },
        "id": "78f4b0d6-4008-4ab3-bd73-0c0db5842ee9",
        "request": {},
        "died": true
    }
}
Result of destroyPengine_promise() promise execution: 
{
    "event": "destroy",
    "id": "78f4b0d6-4008-4ab3-bd73-0c0db5842ee9",
    "pengine": {
        "options": {
            "server": "http://localhost:3030/pengine",
            "application": "tsll",
            "destroy": false,
            "format": "json"
        },
        "id": "78f4b0d6-4008-4ab3-bd73-0c0db5842ee9",
        "died": true
    }
}

```

Moving player from their current location in the **anteroom** to the **first floor hallway**

```prolog
Attempting Prolog query: pengine_execute_single_user_action(move_player_to(player_1,hallway_first_floor),QueryReport)
Received a child object that is not in args/functor format.
Query succeeded. Current solution.
[{"QueryReport":[{"args":[{"args":[{"args":["player_entered_room"],"functor":"event_name"},{"args":["player_1"],"functor":"actor"},{"args":["player"],"functor":"role"},{"args":["entered_room"],"functor":"action"},{"args":["hallway_first_floor"],"functor":"target"},{"args":[{"args":["room_contents"],"functor":"info_type"},{"args":[["player_1"]],"functor":"info_list"}],"functor":"target_info"}],"functor":"details"}],"functor":"event"}]}]
BETTER JSON OBJ: 
{
    "QueryReport": {
        "event": [
            {
                "details": [
                    {
                        "event_name": [
                            "player_entered_room"
                        ]
                    },
                    {
                        "actor": [
                            "player_1"
                        ]
                    },
                    {
                        "role": [
                            "player"
                        ]
                    },
                    {
                        "action": [
                            "entered_room"
                        ]
                    },
                    {
                        "target": [
                            "hallway_first_floor"
                        ]
                    },
                    {
                        "target_info": [
                            {
                                "info_type": [
                                    "room_contents"
                                ]
                            },
                            {
                                "info_list": [
                                    null
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    }
}
No more solutions
Client side Pengine instance successfully destroyed.
Object received:{
    "event": "destroy",
    "id": "63ac0b8e-2956-4d26-b969-460bc6c476b3",
    "pengine": {
        "options": {
            "server": "http://localhost:3030/pengine",
            "application": "tsll",
            "destroy": false,
            "format": "json"
        },
        "id": "63ac0b8e-2956-4d26-b969-460bc6c476b3",
        "request": {},
        "died": true
    }
}
Result of destroyPengine_promise() promise execution: 
{
    "event": "destroy",
    "id": "63ac0b8e-2956-4d26-b969-460bc6c476b3",
    "pengine": {
        "options": {
            "server": "http://localhost:3030/pengine",
            "application": "tsll",
            "destroy": false,
            "format": "json"
        },
        "id": "63ac0b8e-2956-4d26-b969-460bc6c476b3",
        "died": true
    }
}

```

Querying current player location again. Expecting them to still be in the **anteroom** and _not_ the **first floor hallway** :

```prolog
Attempting Prolog query: pengine_execute_single_user_action(get_player_location(PlayerLocation),QueryReport)
Query succeeded. Current solution.
[{"PlayerLocation":"hallway_first_floor","QueryReport":["empty_report"]}]
BETTER JSON OBJ: 
{
    "PlayerLocation": "hallway_first_floor",
    "QueryReport": "empty_report"
}
No more solutions
Client side Pengine instance successfully destroyed.
Object received:{
    "event": "destroy",
    "id": "0844375d-b961-40fa-9c5f-432c672d045c",
    "pengine": {
        "options": {
            "server": "http://localhost:3030/pengine",
            "application": "tsll",
            "destroy": false,
            "format": "json"
        },
        "id": "0844375d-b961-40fa-9c5f-432c672d045c",
        "request": {},
        "died": true
    }
}
Result of destroyPengine_promise() promise execution: 
{
    "event": "destroy",
    "id": "0844375d-b961-40fa-9c5f-432c672d045c",
    "pengine": {
        "options": {
            "server": "http://localhost:3030/pengine",
            "application": "tsll",
            "destroy": false,
            "format": "json"
        },
        "id": "0844375d-b961-40fa-9c5f-432c672d045c",
        "died": true
    }
}

```

I expected the player to **still be in the _anteroom_** since the assertion that moves the player to the new room should have had no permanent effect? However as you can see, the player has indeed moved to the **first floor hallway**.

Where is my understanding incorrect?

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [June 3, 2019, 2:20pm UTC](https://swi-prolog.discourse.group/t/need-clarifications-on-pengines-temporary-module/760/2 "2019-06-03T14:20:22Z")

</div>

That works provided the assert appears in the program you supply with `src_text`. If the assert is done by code imported into the application module it asserts in another module and is persistent. I guess you also needed to declare the interface as safe?

The rule should be that the program you added using the `src_text` argument and all side effects this can create through the system safe predicates leave no traces. The sandbox should not allow changing anything outside the temporary module and that is destroyed on pengine destruction.

If you extend the accessible predicates with predicates that can make permanent changes and you declare these operations safe, changes are persistent.

---

<div class="post-metadata">

**Author:** ![prodog](https://avatars.discourse-cdn.com/v4/letter/p/57b2e6/32.png) [@prodog](https://swi-prolog.discourse.group/u/prodog)\
**Post date:** [June 3, 2019, 2:27pm UTC](https://swi-prolog.discourse.group/t/need-clarifications-on-pengines-temporary-module/760/3 "2019-06-03T14:27:19Z")

</div>

I see. Let me recapitulate to make sure I have it completely right now, using a simple case list.

- Asserts made from code in the `src_text` parameter are **not** permanent
- However, asserts made from code executed on behalf of a query (ask) **are** permanent?
- However again, asserts made by server code _called by code in the src\_text_ parameter **are** permanent? In other words, even if the call originates in code in the `src_text` parameter, if that code calls predicates in the main server code base that does an assert, those asserts **are** permanent?

If the above table is correct, then the only thing that determines if an assert is temporary or not is if the actual `assert()` call is in the `src-text` parameter. If the `assert()` call is in the code in the `src_test` parameter then it is temporary. If it is outside of it in the main server code, then it is permanent regardless of where the original query originated… Is that true?

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [June 3, 2019, 9:02pm UTC](https://swi-prolog.discourse.group/t/need-clarifications-on-pengines-temporary-module/760/4 "2019-06-03T21:02:52Z")

</div>

It depends 🙂 What matters is the module in which the clause is asserted. If this is the pengine temporary module, it is gone after the pengine dies. You can define a _meta\_predicate_ in code outside the temporary module that still asserts into the Pengine module. For example, this asserts in the Pengine module.

```prolog
:- meta_predicate my_assert(:).

my_assert(Term) :-
     asserta(Term).

```

While without the `:- meta_predicate my_assert(:).` declaration it asserts in the module `my_assert/1` is defined.
