Skip to content

Added support for Last-Modified and ETag #8

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

Merged
merged 19 commits into from
Aug 2, 2016
Merged

Added support for Last-Modified and ETag #8

merged 19 commits into from
Aug 2, 2016

Conversation

Nyholm
Copy link
Member

@Nyholm Nyholm commented Jul 29, 2016

Q A
Bug fix? no
New feature? yes
BC breaks? yes
Deprecations? no
Related tickets fixes #2
Documentation
License MIT

What's in this PR?

We should allow the server to answer 304 which allows us to use a response in the cache.
The BC break here is that all existing items in the cache will be invalid. Is that an issue? It is a cache and not a storage.

I introduced a new config parameter cache_lifetime that says how long the item should be in cache without it being used.

I did also add a few parameters to the array we store in the cache such as expiresAt, createdAt, etag.

To Do

  • Fix the tests

$cacheItem->set($data)->expiresAfter($this->config['cache_lifetime'] + $data['expiresAt']);
$this->pool->save($cacheItem);

return $this->createResponseFromCacheItem($cacheItem);
Copy link
Member

Choose a reason for hiding this comment

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

What if the server responds with 304 but there is no cache?

Copy link
Member Author

Choose a reason for hiding this comment

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

We do now that it is a cache. Or else the If-Modified-Since and If-None-Match would not have been added. And correct me if I'm wrong but I don't think the server will answer 304 without those headers in the request.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, those headers may have been added before. I'll just make sure to pass the response then.

@sagikazarmark
Copy link
Member

Why do we need cache lifetime? Normally the server tells us how long it should be cached, doesn't it?

@Nyholm
Copy link
Member Author

Nyholm commented Jul 29, 2016

Yes, but we would like to have the possibility to serve an expired response if the server answers 304.

@Nyholm
Copy link
Member Author

Nyholm commented Jul 29, 2016

T0: We make a request. Server responds saying the response is valid until T10. Return response form server
T5: We make a request. The response is in the cache and we know it is valid until T10. Return response from cache
T15: We make a request. The response is in the cache but is stale. We ask the server about the response and server answer 304 and that the response is valid until T25. Return response from cache
T20: We make a request. The response is in the cache and we know it is valid until T25. Return response from cache


$pool->getItem('e3b717d5883a45ef9493d009741f7c64')->shouldBeCalled()->willReturn($item);
$item->isHit()->willReturn(false);
$item->set(['response' => $response, 'body' => $httpBody])->willReturn($item)->shouldBeCalled();
$item->expiresAfter(60)->willReturn($item)->shouldBeCalled();
$item->set()->willReturn($item)->shouldBeCalled();
Copy link
Member Author

Choose a reason for hiding this comment

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

I can't figure out a good way to write this line. I cant specify the exact data since it is dependent on time().

Can I say $item->set(<any argument>)->willRetu....?

@Nyholm
Copy link
Member Author

Nyholm commented Jul 31, 2016

I've figured out the tests and I found some bugs.

Im done with the code changes and this PR is ready for review.

@@ -194,11 +231,73 @@ private function getMaxAge(ResponseInterface $response)
private function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'cache_lifetime' => 2592000, // 30 days
Copy link
Contributor

Choose a reason for hiding this comment

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

might be clearer to actually have an arithmetic expression here since it's only executed once

@Nyholm
Copy link
Member Author

Nyholm commented Aug 2, 2016

Thank you @GrahamCampbell. I've update the PR according to your suggestions.

@@ -15,7 +16,7 @@ class CachePluginSpec extends ObjectBehavior
{
function let(CacheItemPoolInterface $pool, StreamFactory $streamFactory)
{
$this->beConstructedWith($pool, $streamFactory, ['default_ttl'=>60]);
$this->beConstructedWith($pool, $streamFactory, ['default_ttl'=>60, 'cache_lifetime'=>1000]);
Copy link
Contributor

Choose a reason for hiding this comment

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

odd cs?

$this->beConstructedWith($pool, $streamFactory, ['default_ttl'=>60, 'cache_lifetime'=>1000]);
$this->beConstructedWith($pool, $streamFactory, [
'default_ttl' => 60,
'cache_lifetime'=>1000
Copy link
Contributor

Choose a reason for hiding this comment

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

missing spaces?

}
}

return;
Copy link
Contributor

Choose a reason for hiding this comment

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

don't need this statement?

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

yeh, i replied there

$cacheItem
->expiresAfter($this->config['cache_lifetime'] + $maxAge)
->set([
'response' => $response,
Copy link
Contributor

Choose a reason for hiding this comment

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

is this one level not enough indented?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thank you. But shouldn't StyleCi pick this up?

Copy link
Contributor

Choose a reason for hiding this comment

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

Symfony has no rules about indentation like this I think?

@GrahamCampbell
Copy link
Contributor

Looks good. I've not physically tested this in the real world yet though.

$maxAge = $this->getMaxAge($response);
$currentTime = time();
$cacheItem
->expiresAfter($this->config['cache_lifetime'] + $maxAge)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are we doing this please?

Copy link
Member Author

Choose a reason for hiding this comment

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

We would like to serve Responses that the server once said should expire.

See #8 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

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

when doing cache validation, we keep outdated caches and send If-Modified-Since / If-None-Match requests to the server to check if the cache is ok to be used. we might add some comment in the code though, to make it clear.

@dbu
Copy link
Contributor

dbu commented Aug 2, 2016

went over the code, looks good to me.

for a moment i was wondering about stale-while-validate but this is just content validation and not advanced proxy operations. in async mode we theoretically could use stale-while-validate to return the expired response and re-fetch to our local cache. but this has nothing to do with this PR and anyways seems like a bad use case - one should use a dedicated caching proxy for such things, not implement this on client side.

@Nyholm
Copy link
Member Author

Nyholm commented Aug 2, 2016

TODO:

@Nyholm
Copy link
Member Author

Nyholm commented Aug 2, 2016

We use issets.

This PR is ready to be merged

@sagikazarmark sagikazarmark merged commit 4bf191d into master Aug 2, 2016
@sagikazarmark sagikazarmark deleted the issue-2 branch August 2, 2016 20:55
@sagikazarmark
Copy link
Member

Thanks, will tag a release soon.

@Nyholm
Copy link
Member Author

Nyholm commented Aug 2, 2016

Awesome. Thank you for all the reviews and feedback.

This was referenced Aug 3, 2016
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

Successfully merging this pull request may close these issues.

Cache Validation
4 participants