Skip to content

Bug: MemcachedHandler::decrement() produces the opposite sign of File/Redis/Predis for a non-existent key #10510

Description

@mdalikadar

PHP Version

8.2

CodeIgniter4 Version

4.7.5-dev

CodeIgniter4 Installation Method

Git

Which operating systems have you tested for this bug?

macOS

Which server did you use?

cli-server (PHP built-in webserver)

Environment

development

Database

No response

What happened?

Description

MemcachedHandler::decrement() behaves inconsistently with the other cache
handlers (File, Redis, Predis) when the key being decremented does not
yet exist. This is already flagged in the code with a // FIXME comment,
but not resolved:

https://github.com/codeigniter4/CodeIgniter4/blob/develop/system/Cache/Handlers/MemcachedHandler.php#L179

public function decrement(string $key, int $offset = 1): false|int
{
    if (! $this->config['raw']) {
        return false;
    }

    $key = static::validateKey($key, $this->prefix);

    // FIXME: third parameter isn't other handler actions.

    return $this->memcached->decrement($key, $offset, $offset, 60);
}

How to see it

$cache = \Config\Services::cache(); // memcached handler, 'raw' => true

$cache->decrement('brand_new_key', 5);
// -> 5   (positive!)

Now try the same thing with File, Redis, or Predis instead — they all give:

$cache->decrement('brand_new_key', 5);
// -> -5

What I'd expect

If I decrement a key by 5, I'd expect a negative number back when it starts from nothing — like every other handler does. Memcached gives the opposite sign, which feels like a bug you could easily not notice until you switch cache drivers between dev and prod and your numbers suddenly flip.

Why this happens

I checked the PHP docs for Memcached::decrement() — the 3rd argument (initial_value) is used as-is if the key doesn't exist yet, it's not something the offset gets subtracted from. So passing $offset there just plants the key at +$offset instead of decrementing from zero.

(increment() doesn't have this problem, by the way — it's just a lucky coincidence that 0 + $offset and passing $offset as the initial value land on the same number.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugVerified issues on the current code behavior or pull requests that will fix them

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions