Skip to content

Instantly share code, notes, and snippets.

@jwage
Last active September 21, 2017 00:59
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save jwage/36b9da260fb7c841a953e924bb33d846 to your computer and use it in GitHub Desktop.
This is pseudo code to demonstrate a problem
<?php
$rules = [
[
'id' => 1,
'expression' => 'x = 1 AND y = 2 AND userLogCount <= 5',
],
];
$expressionLanguage = $container->get('expression_language');
$context = [
'x' => 1,
'y' => 2,
];
$userId = 1;
foreach ($rules as $rule) {
$context['userLogCount'] = exec('SELECT COUNT(*) FROM reward_log WHERE ruleId = :ruleId AND userId = :userId', [
'ruleId' => $rule['id'],
'userId' => $userId
]);
if ($expressionLanguage->evaluate($rule['expression'], $context)) {
$rule->insertLogEntry();
$rule->executeAction();
}
}
@jwage
Copy link
Author

jwage commented Sep 21, 2017

This is the only way I can think of to avoid the problem by implementing some kind of atomic locking per userId using redis or something.

<?php

$userId = 1;

takeOrWaitForLock($userId);

$rules = [
    [
        'id' => 1,
        'expression' => 'x = 1 AND y = 2 AND userLogCount <= 5',
    ],
];

$expressionLanguage = $container->get('expression_language');

$context = [
    'x' => 1,
    'y' => 2,
];

foreach ($rules as $rule) {

    $context['userLogCount'] = exec('SELECT COUNT(*) FROM reward_log WHERE ruleId = :ruleId AND userId = :userId', [
        'ruleId' => $rule['id'],
        'userId' => $userId
    ]);

    if ($expressionLanguage->evaluate($rule, $context)) {
        $rule->insertLogEntry();

        $rule->executeAction();
    }    
}

releaseLock($userId);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment