Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Set ttl to specific cache key for Redis Storage Adapter #10

Closed

Conversation

pensiero
Copy link
Contributor

  • Implemented the internalTouchItem method inside Storage\Adapter\Redis that allow to touch a Redis item.
  • Implemented the _ttl metadata, that return the remaining tll of a specific key

Thanks to @marc-mabe to help me understanding what to do!

Refer to #5, I have created a new PR to clean my code from other local branches that was creating troubles.

* In redis 2.6, the command return -1 if the key does not exist
* In redis > 2.8, the command return -2 if the key does not exist, -1 if the key exists but has no associated expire
*/
$remainingTimeout = $redis->ttl($this->namespacePrefix . $normalizedKey);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be be compatible with other adapters getMetadata should return false in the case the item doesn't exist.
-> from StorageInterface::getMetadata() : @return array|bool Metadata on success, false on failure where a failure means the request can't be made but it's not an error. An error would result in an exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm returning false if the the item is not found (https://github.com/zendframework/zend-cache/pull/10/files#diff-8799c8aa6a52387ce614380b5db83f76R491)

Did you mean that I have to update the docblock?

@marc-mabe
Copy link
Member

Only the one comment above.

Please let run unit tests for this adapter and check code coverage for your new code. I know the version specific lines will only be tested if you run the specific version but one of this version should be well tested and all the other new code around.

thanks!

@pensiero
Copy link
Contributor Author

@marc-mabe I can't do also the test for specific versions.. if someone can do that, ok

@marc-mabe
Copy link
Member

@pensiero It's very ok if you test only your version I think

@pensiero
Copy link
Contributor Author

@marc-mabe then yes! it's ready 👍

@marc-mabe
Copy link
Member

@pensiero but some tests failed - see continuous-integration/travis-ci/pr

@pensiero
Copy link
Contributor Author

@marc-mabe it's strange, because in my environment the test pass... and I'm using php 5.6, that fails in Travis. Could it be for some configs? I've enabled TESTS_ZEND_CACHE_REDIS_ENABLED and started the redis server...anything else?

@Maks3w
Copy link
Member

Maks3w commented Jun 23, 2015

Could you rebase against current master? Current master have many improvements for integration tests

@pensiero
Copy link
Contributor Author

@Maks3w done, but however test fails

@marc-mabe
Copy link
Member

@pensiero If I look @ https://coveralls.io/builds/2883342/source?filename=src%2FStorage%2FAdapter%2FRedis.php I see the tests ran with a redis version >= 2.0 and < 2.6 with the logic:

// ...

// redis >= 2
// The command 'pttl' is not supported but 'ttl'
// The command 'ttl' returns 0 if the item does not exist same as if the item is going to be expired
// NOTE: In case of ttl=0 we return false because the item is going to be expired in a very near future
//       and then doesn't exist any more
} elseif (version_compare($redisVersion, '2', '>=')) {
    $ttl = $redis->ttl($this->namespacePrefix . $normalizedKey);
    if ($ttl <= 0) {
        return false;
    }
    $metadata['ttl'] = $ttl;
// ...

One of the tests failing looks like this:

public function testGetMetadata()
{
    $capabilities = $this->_storage->getCapabilities();
    $supportedMetadatas = $capabilities->getSupportedMetadata();
    $this->assertTrue($this->_storage->setItem('key', 'value'));
    $metadata = $this->_storage->getMetadata('key');
    $this->assertInternalType('array', $metadata); // <- failes
    // ...
}

As of the test doesn't set a specific TTL it will be the default one for infinite lifetime (TTL=0). I could think of that redis could return ttl=0 in this case, too. So a returned ttl=0 could would mean one of the following:

  • item exists with infinite TTL
  • item exists but item will expire in the very near future (no second based TTL left)
  • item doesn't exist

If this is the case we have to check for $this->internalHasItem($normalizedKey) as well:

    if ($ttl <= 0 && !$this->internalHasItem($normalizedKey)) {
        return false;
    }

@marc-mabe
Copy link
Member

PS: you did not rebased against master. You have merged the master into your branch.
Please use git fetch {remote} && git rebase {remote}/master ;)

@pensiero
Copy link
Contributor Author

Ok we are making progress. Now I'm returning null if the item has no associated expire (whatever the version is) and false if the items doesn't exist.

However testGetMetadata in CommonAdapterTest is expecting an array, even if this is empty. @marc-mabe do you think I can replace the null return with an empty array?

@marc-mabe
Copy link
Member

@pensiero From interface:

    /**
     * Get metadata of an item.
     *
     * @param  string $key
     * @return array|bool Metadata on success, false on failure
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function getMetadata($key);

@pensiero
Copy link
Contributor Author

@marc-mabe if as you said the tests are running with redis version >= 2 and < 2.6, how can this return a $metadata['ttl'] of -1 (instead of expected 0), basing on this case? thanks

@marc-mabe
Copy link
Member

@pensiero In this case you should return an array with ttl set to NULL instead of returning null

@pensiero
Copy link
Contributor Author

@marc-mabe it's what I did: https://github.com/pensiero/zend-cache/blob/feature/set-ttl-redis-adapter/src/Storage/Adapter/Redis.php#L531
but it seems that it's not the problem (or maybe I did not understand what you said)

@marc-mabe
Copy link
Member

                    // ...
                    $metadata['ttl'] = null;
                }
                $metadata['ttl'] = $ttl;
                // ...

It's not working this way as the raw TTL returned by redis will overwrite the ttl 2 lines later ;)

@pensiero
Copy link
Contributor Author

WTF! 😬 let's see if now they pass...

@pensiero
Copy link
Contributor Author

It's seems ok, what do you think @marc-mabe ?

@marc-mabe
Copy link
Member

Looks better now but there is the same issue with redis version >= 2.6 - see https://github.com/zendframework/zend-cache/pull/10/files#diff-8799c8aa6a52387ce614380b5db83f76R516

And please check your coding style - see https://travis-ci.org/zendframework/zend-cache/jobs/68730134

Again - please make a rebase with current master and combine all your commits into a single one
(https://help.github.com/articles/about-git-rebase/)

git fetch <upstream>
git rebase -i {upstream}/master

@pensiero pensiero force-pushed the feature/set-ttl-redis-adapter branch from dae5372 to ab997e2 Compare June 29, 2015 23:03
@pensiero
Copy link
Contributor Author

So nice rebasing! First time used! Thanks a lot @marc-mabe (never end to learning, I'm very happy of this).

@marc-mabe
Copy link
Member

I think it looks good now 👍
@Maks3w ping

@pensiero
Copy link
Contributor Author

great! thanks a lot marc!

@pensiero
Copy link
Contributor Author

Is there anything else I can do?

@weierophinney weierophinney added this to the 2.5.2 milestone Jul 16, 2015
@weierophinney weierophinney self-assigned this Jul 16, 2015
weierophinney added a commit that referenced this pull request Jul 16, 2015
weierophinney added a commit that referenced this pull request Jul 16, 2015
@pensiero pensiero deleted the feature/set-ttl-redis-adapter branch September 7, 2015 10:11
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants