Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Berdir created an issue. See original summary.

Lendude’s picture

Status: Active » Needs review
FileSize
5.25 KB

Something like this?

The test coverage build on the kernel test base class from #3096227: poll-results.html.twig documents 'vote' as the current user's vote, but is always empty so this will fail until that lands. Might want to do it the other way around ¯\_(ツ)_/¯

This does take into account the current user switching during the request (unlikely, but who knows), but not the vote changing during the request (even less likely I think)

Berdir’s picture

> but not the vote changing during the request (even less likely I think)

Might not be that uncommon? Isn't submitting an ajax vote request that results in rendering the results exactly that? first submission builds the form, checks the vote, shows the form, submits that, rebuilds the form and then it needs to show the results.

But that should be easy to handle, just unset the statically cached results when you save the vote in the same service.

Lendude’s picture

Hmm the vote scenario doesn't fail, but when using the 'cancel vote' button it does! Nice catch.

This now unsets the static cache on save/cancel/delete. Expanded the javascript test to also press the cancel button, which fails nicely with #2

Lendude’s picture

Berdir’s picture

Status: Needs review » Needs work
  1. +++ b/src/PollVoteStorage.php
    @@ -57,6 +64,8 @@ class PollVoteStorage implements PollVoteStorageInterface {
         $this->cacheTagsInvalidator->invalidateTags(['poll-votes:' . $poll->id()]);
    +    // Invalidate the static cache of votes.
    +    $this->currentUserVote = NULL;
       }
    

    resetting it to NULL seems strange, that's not the correct type according to the @var, but neither is it initialized to an array.

    I'd initialize and reset it to [].

  2. +++ b/src/PollVoteStorage.php
    @@ -121,22 +134,58 @@ class PollVoteStorage implements PollVoteStorageInterface {
    +  protected function storeUserVote(PollInterface $poll, $uid, $value) {
    +    $key = $poll->id() . ':' . $uid;
    ...
    +  }
    +
    

    I'm not sure these two helper methods are necessary, means the logic for the key is actually in two places, if we inline it in getUserVote() then it's just in one place.

    Also, it's pretty theoretical, but the static cache doesn't consider the hostname yet for an anonymous user, it would be weird but not impossible to e.g. alter the global request object to read values of different IP's or something like that ;)

    People have different opinions on early return, but I like it, especially in such a static-cache pattern. Would also make the patch much more readable, as only needs to make minimal changes in the existing code.

    So I'd do something like this:

    
    $key = $poll->id() . ':' . ($uid ?: $ip);
    if (isset($this->currentUserVote[$key]) {
      return $this->currentUserVote[$key];
    }
    $this->currentUserVote[$key] = FALSE;
    
    // .., just change query fetch to assign to $this->currentUserVote[$key].
    
    return $this->currentUserVote[$key];
    
  1. +++ b/tests/src/Kernel/PollVoteStorageTest.php
    @@ -0,0 +1,62 @@
    +    // Test with an authenticated user.
    +    $this->setUpCurrentUser(['uid' => 2]);
    +    $choice_id = $poll->get('choice')->get(6)->getValue()['target_id'];
    +    $this->saveVote($poll, $choice_id);
    

    Hm. In other issue I commented on going through current user being a bit strange, but I forgot about poll vote storage using that too, so I think that makes sense. Ignore that part then over there.

    Still, the choice_id can be simplified to $poll->get('choice')->get(6)->target_id (or $poll->get('choice')[6]->target_id, but get() + array access looks a bit strange). and with the suggestion in the other issue to only create 2-3 choices by default, you'd need to make it 1 or 2 I suppose.

  2. +++ b/tests/src/Kernel/PollVoteStorageTest.php
    @@ -0,0 +1,62 @@
    +    $connection->query("DELETE FROM {poll_vote}")->execute();
    

    ->delete('poll_vote')->execute()? Also, query() already executes the query, so that should actually be a fatal, which we don't see yet without the base class.

Lendude’s picture

#6.1 fixed
#6.2 was over thinking stuff, yes this is much cleaner
#6.3 fixed
#6.4 ->execute() doesn't fatal, it also doesn't do anything else :), changed to ->delete()

Adding a version with the kernel test base included so we can see the test run

Berdir’s picture

Status: Needs review » Fixed

get(2) didn't work anymore as the base class now defaults to only 2 choices, changed it to get(1), then the test passed, committed with that.

  • Berdir committed bfa597f on 8.x-1.x authored by Lendude
    Issue #3094531 by Lendude, Berdir: Statically cache PollVoteStorage::...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.