Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$page->increment() and $page->decrement() do not work properly (if at all) when called in parallel #6724

Open
owzim opened this issue Oct 6, 2024 · 0 comments

Comments

@owzim
Copy link

owzim commented Oct 6, 2024

Description

When $page->increment() (or decrement) on a certain page is called in parallel, i.e. when many users are visiting a page in parallel, that executes that certain code, the value is not incremented properly.

The reason behind that is pretty clear: when the value is incremented by one process, the next parallel process does not know of that change because it has already started to read the value before the previous process incremented it.

It's not so much about hundreds of users visiting a page in parallel, it's more about that the chance that even only two parallel visitors cause this scenario is not zero. Data integrity is lost in this case.

Databases can handle such scenarios where multiple processes or threads are trying to increment a value in parallel. This is typically managed using transactions and locking mechanisms that ensure data consistency in concurrent operations.

Expected behavior

The value should be incremented properly

To reproduce

1. check out starterkit

git clone https://github.com/getkirby/starterkit.git page-increment
cd page-increment
composer install

2. Extend the home blueprint

site/blueprints/pages/home.yml

@@ -23,6 +23,9 @@ sections:
       subheadline:
         type: text
         width: 1/2
+      incrementor:
+        type: number
+        width: 1/2

3. Add initial value 0 to the home page

content/home/home.txt

@@ -10,4 +10,8 @@ Subheadline: A fully documented example project
 
 ----
 
+Incrementor: 0
+
+----
+
 Uuid: wljMYhm0m3e9QOwC

4. create a php script for the incrementing

increment-home.php

<?php

use Kirby\Cms\App as Kirby;

require_once __DIR__ . '/kirby/bootstrap.php';

Kirby::instance()->impersonate('kirby', function() {
    kirby()->page('home')->increment('incrementor', 1, 100);
});

5. create a bash script that calls the incrementor script in parallel 10 times

touch increment-home-parallel.sh && chmod +x increment-home-parallel.sh

#!/usr/bin/env bash

TIMES="${1:-10}"

for i in $(seq 1 $TIMES)
do
    (
        echo "Calling script $i"
        php increment-home.php
    ) &
done
wait

6. call the script

./increment-home-parallel.sh

See that the value was not incremented properly, should be 10 but is much lower

-Incrementor: 0
+Incrementor: 3

Your setup

Kirby Version: latest, see starterkit

*Your system

  • PHP 8.2.21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant