Ahh, I see. I can reproduce your result by omitting the %updating.
I guess the store functions, like the file functions, are updating (but
they just don't like to admit it 😀.)

Thanks
/Andy

On Mon, 27 Jan 2025 at 17:37, Marco Lettere <m.lett...@gmail.com> wrote:

> Hi Andy,
>
> sorry for not specifying but we usually set the following property in the
> .basex file in order to being able to blend updating and non updating
> functions.
>
> # Local Options
> MIXUPDATES = true
>
> M.
> On 27/01/25 18:30, Andy Bunce wrote:
>
> Hi Marco,
>
> When I try your code (with 10.7 or 11.6 ) I get
>
> [XPTY0004] Function is updating: %updating fn() as empty-sequence()...
>
> Which is what I would expect from the hint in the documentation [1]
> Do you not get this error message?
>
> /Andy
>
> [1] https://docs.basex.org/main/XQuery_Functions#xquery:fork-join
>
> On Mon, 27 Jan 2025 at 16:41, Marco Lettere <m.lett...@gmail.com> wrote:
>
>> Thanks for checking into this Christian.
>>
>> I'm experimenting with some sort of workflow oriented programming because
>> our projects are getting more and more complex and we'd like to have a way
>> of "standardizing" some patterns and getting a bit of introspection and
>> observability of what happens to a complex workflow.
>>
>> We'd love to use the store as a shared memory among functions annotated
>> as tasks for many reasons such as keeping a global log of the workflow,
>> reducing dependency on function signatures or chaining together tasks
>> executed in subsequent continuations (aka subworkflows).
>>
>> Those are kind of things that you can benefit from when using workflow
>> engines. But we don't want to rely on those because they have a huge impact
>> in terms of provisioning and maintenance. So we wanted to check whether a
>> light weight solution in code is viable.
>>
>> I'm currently rewriting the code to use a DB instead of the store. But it
>> would have been so nice to have it without requiring an external db
>> server... But for example, as soon as I have two tasks running in parallel
>> (fork-join) and they want to add a log line to the sequence of logs that
>> introduces the risk of loosing data.
>>
>> Hope it clears up the intent even if a bit convoluted explanation. :-)
>> Ciao,
>> M.
>>
>> On 27/01/25 17:15, Christian Grün wrote:
>>
>> Hi Marco,
>>
>> even if %basex:lock can be added to specific function calls, it will only
>> be considered before the full query is evaluated. As a consequence, your
>> current query will only be evaluated if no other updating query with CONFIG
>> locks is running at the same time.
>>
>> Apart from that, the store functions are not handled by our transaction
>> management. Instead, they will be immediately executed, and we do our best
>> to ensure that parallel store operations do not result in inconsistent
>> states (basically by treating each store update as an atomic operation). We
>> may need to clarify this in our documentation.
>>
>> What has been your motivation for adding entries to the store in parallel?
>>
>> Best,
>> Christian
>>
>>
>> Marco Lettere <m.lett...@gmail.com> schrieb am Mi., 22. Jan. 2025, 17:21:
>>
>>> Dear all,
>>>
>>> I'm wondering why the code in [1] is not working as expected. Expected
>>> means getting back a map with 100 keys.
>>>
>>> Instead I get a random number of keys which denotes the fact (proved by
>>> tracing) that the map in store is updated concurrently without
>>> respecting the lock annotations.
>>>
>>> Is there a way to obtain synchronized access to key/values of the
>>> default store?
>>>
>>> Thank you.
>>>
>>> Kind regards,
>>>
>>> Marco.
>>>
>>> [1]
>>>
>>> declare %updating %basex:lock('CONFIG') function local:write($k as
>>> xs:string) {
>>>    store:put("config", map:put(store:get("config"), $k,
>>> random:integer(10)))
>>> };
>>>
>>> let $s1 := store:put("config", map{})
>>> let $s2 := xquery:fork-join(for $i in (1 to 100) return function(){
>>> local:write("key" || $i) })
>>> return count(map:keys(store:get("config")))
>>>
>>>

Reply via email to