When caching is enabled, and anonymous users are allowed to vote, the poll block doesn't change to show results after a vote has been recorded.
| Comment | File | Size | Author |
|---|---|---|---|
| #39 | poll-cache-anonymous-2.patch | 10.42 KB | c960657 |
| #35 | poll-cache-anonymous-1.patch | 10.25 KB | c960657 |
| #11 | poll-not-compatible-with-caching.patch | 2.19 KB | gábor hojtsy |
| #5 | poll_11.patch | 320 bytes | chx |
Comments
Comment #1
jo1ene commentedCould not reproduce this problem in 4.6.3 and it doesn't appear in the 4.7 beta.
Comment #2
luperry commentedI'm experiencing the same issue. But it only happens on firefox and opera, not on IE. Clearing the browser cache didn't help either.
Comment #3
killes@www.drop.org commentedif it is a brower problem then this is most likely a theme issue
Comment #4
luperry commentedI just tested it again, it seems IE has the problem as well.
The bug persists on the default bluemarine theme, so I don't think it's a theme problem. I was also able to reproduce the bug on the drupal demo site at http://demo.opensourcecms.com/drupal/, the username is admin, password is demo. To reproduce the bug:
1. make sure page caching is enabled.
2. make sure anonymous is allowed to vote.
3. create a poll as admin.
4. log out, and vote on the poll as anonymous.
5. go back to top page, you'll see the poll is presented to you as if you never voted(the cached page).
It's fine if the poll shown to all anonymous users are in the "unvoted state", but it often occurs that the cached page is when the user has already casted the vote, then other anonymous users will not be able to vote on the poll, that's what the major problem is.
Comment #5
chx commentedVerified. I set it to CVS because that's what I am patching against but I think this applies to 4.7 as well.
Comment #6
drummCommitted to HEAD.
It is sad to see another cache_clear_all(), but it has to be done.
Comment #7
luperry commentedthis leads to another problem. after clear_cache_all(), if an anonymous user who has already casted the vote immediately loads the page, all subsequent anonymous users who haven't vote would be unable to vote, because the cached page is the one that shows the result.
Comment #8
tormu commentedHas this been solved already? It seems to be broken still, at least in 4.7.3
Comment #9
alonpeer commentedI'm having the same problem.
One solution I can think of (except for disabling cache...) is to modify the poll module to always display the poll question and never the poll results on the block view. This way, even after an anonymous user voted, he will not see the poll results on the block (only on the poll page) and if he surfs to other pages and triggers their caching, the poll results won't get cached.
What do you think?
BTW, I'm pretty sure this problem persists in Ver 5 after checking it on http://demo.opensourcecms.com/drupal/. Can anyone back me up on this?
Comment #10
gábor hojtsyWell, this is how anonymous page caching works. It caches the whole page without consideration to what might or might not need to be personalized to any anonymous user. Poll voting might be one of these things to personalize per anonymous users, but this needs a complete rethink of how Drupal caching works. Not in Drupal 6.
Comment #11
gábor hojtsyActually what we can do in Drupal 6 is to disallow anonymous voting when page caching is on, and display a warning about this on the permissions page.
Comment #12
moshe weitzman commentedyou could personalize in the submit handler, instead of in the form (i.e. record IP address and so on). I think it is a pretty horrid restriction to not allow voting on cached pages. this makes it useless for all media sites and sites of any size.
Comment #13
gábor hojtsyMoshe: it is not at all poll module's limitation. We cannot do anything to support it. When a poll form is cached to a page, all anonymous voters will get the poll form, as it is in the page cached. When a poll result is cached in a page output all anonymous visitors get vote results in the output. It is basically a sign of how the anonymous caching works, it is all or nothing on the page. If all is cached, we cannot display a voting result or form depending on whether the anonymous user at hand voted before or not. So as far as I see, the problem cannot be solved with anonymous page caching and is the same issue for any module/block which tries to show personalized data to anonymous users without refraining to JavaScript tricks to overcome the page cache.
Comment #14
JirkaRybka commentedTheoretically (not tested yet): How does the new block cache play with this? I can't see the caching mode specified anywhere in poll.module, so I guess it might get cached per-role and so wrong again. Caching per-user might be better, but does that help for anonymous (with page caching off)? Just thinking aloud, nothing tested...
Comment #15
gábor hojtsyHm, indeed we could cache for authenticated users per user, but for anon users we should not cache the block at all (when page caching is turned off and anonymous voting is allowed). I did not look into what can we specify for block caching, whether it can handle this kind of dynamic expression or we can only set it to not cache.
Comment #16
moshe weitzman commentedWe could certainly allow anonymous to vote; the problem ithat Gabor rightly describes we can't easily choose to always show them the results after they voted like authenticated users.
Comment #17
gábor hojtsyNo, we cannot allow anonymous to vote. After someone voted, he should see the result page, not the form. Before someone privileged to vote voted, he should see the form. Anonymous page caching does not distinguish between different instances of anonymous, so we cannot display the form for some and the result for some other anonymous visitors. We either display the form to all, but then anonymous users can vote as many as they'd like or the form is displayed even though they get an error message when they try to
whatvote, or always display the result, as this patch does, and disallow voting. Is any of the two options for voting better than disallow voting?Comment #18
JirkaRybka commentedAnother option might be (hackish, I know...) to drupal_set_message() on the form page (inviting the user to vote / reminding that he already voted), which then excludes the page from caching. But that's a bit ugly, and doesn't solve the block-version of polls (unless we set a message there too, which is probably quite inacceptable for a typical frontpage-block). Just thinking aloud. And since this basically means canceling the page caching, we might as well just document it and let the user deal with the cache settings on the UI; so finally I circled back to the original issue here. Hm. (We're perhaps missing some NO_CACHE option in general for pages, like blocks have)
Comment #19
tormu commentedThat's the way we've handled it, couldn't think of anything else since we certainly need the caching to be on. On http://radio86.co.uk/ you can see a poll at the left below the menu inviting the person to vote - then with cacheexclude module every URL with /poll/ is NOT cached and the voting works there.
As said, now there's one click before the user really can vote, but at least we can keep the voting feature while getting the performance boost of cache for 99.6% of the page hits (since the hits to paths with /poll/ are marginal).
I was really surprised that the poll module is a core module, but doesn't have a clear indication that it doesn't work for anonymous if the caching is on. I thought I was doing something wrong for hours before finally getting the hang of what's causing it.
Comment #20
gábor hojtsySo we either leave this broken in Drupal 6 as it is, or add a message and disable voting as I suggested. We don't have any facilities in core to exclude some pages from caching. The solution I proposed still allows an implementation which filps the 'cache' setting depending on path, so that the poll node paths allow voting still (I bet you use url aliasing to achieve this BTW, as the core has no special path for polls).
Comments?
Comment #21
catchBumping to D7, this is still an issue.
Comment #22
moshe weitzman commentedSubscribe. Got bit by this today during a site launch.
Comment #23
moshe weitzman commentedearlier we heard "always display the poll question and never the poll results on the block view". i agree with this. the only downside is that the voter would usually not get good feedback after submitting. thats easily resolved with a drupal_set_message() in the poll vote submit handler. when a dsm() is shown on a page, the page is exempt from page cache so no worries. yes, all users will get anon users will get form_build_id but i don't see a problem in this case.
Comment #24
emackn commentedsubscribing, currently battling.
Comment #25
emackn commentedOur particular issue is that we are displaying the poll on the home page. Since we are caching, all anonymous users, get the same cid, and can vote, but after the first results block is displayed, all subsequent page loads show the form again, since the homepage is still in the cache.
Looking through the poll code, in poll_vote, the call to cache_clear_all isn't clearing the cache at all, which surprised me.
We are going to try a workaround of using some javascript DOM magic to pull in a custom callback for the poll form and results and see it that works.
Comment #26
dave reidComment #27
cburschkaThere is a patch, but it is not for Drupal 7. Judging by the copious discussion, it seems we aren't yet clear on how to solve this problem in D7, so "active" is probably better than "needs work".
Edit: copious, not copies. My English skills suffer when I get tired.
Comment #28
greg.harveyTo expand on moshe in #23:
I like this idea too, but to expand it, why not split the Poll block in to three separate blocks. One is the original block, as it is now, which can be used on sites where caching is not an issue, one shows *only* the voting form and one shows only the Poll results. People with page caching issues can opt to only show the form block, or maybe show both blocks - takes up a bit more real-estate and results will take a little time to refresh, but I don't see a problem with that. It would certainly provide a little more flexibility to aid people fighting with the Drupal page cache.
I can have a crack at this if folk agree it's a sensible compromise...
Ps - I know the code freeze has passed, but at least if there's a D7 patch people agree on, a D8 patch should follow without issue.
Comment #29
greg.harveyAs an aside, I saw Earl's Panels 3 talk at DrupalCon Paris and there was some interesting discussion around how Panels does caching and how it gets rid of problems like these. If you have a theme with no regions, the block module is completely "off" and does not have any impact on site performance. The performance *overhead* of Panels pretty much matches blocks weight-for-weight, so you don't gain or lose anything by swapping out blocks for panels. However, you no longer need to use Drupal page caching if you use Panels caching, which is controllable on a region-by-region basis!
In theory you could use panel pages instead of traditional blocks and regions, now Panels 3.x is stable, forget Drupal page caching and use Panels to manage caching instead. Then you could exclude the Poll block, or your shopping basket block, or whatever else it is that doesn't play nice with page caching, from the Panels caching. Now that's *very* cool (but also *very* experimental - experienced users only, but it looks good).
I intend to try this technique, just for kicks, on my company website. =)
Comment #30
moshe weitzman commented@greg.harvey - your proposal sounds good for some sites, but bigger sites absolutely need a page cache. they need it so bad that even drupal's page cache is insufficient. they use typically use reverse proxy cache like squid/varnish. my proposal to always show the poll question and not the poll answer on cached pages is compatible with sites like these.
Comment #31
greg.harvey@moshe Absolutely, fair point. I forgot I said I'd look at your solution and try to provide a patch, because I think you're right - it's really needed. Thanks for bringing it back to my attention. I have something to do on Nodequeue this week, but I'll keep this issue open in my browser and maybe tackle next week. =)
Comment #32
alanburke commentedSubscribe.
ESI style caching needed here, or javascript based updating of the block perhaps.
It's more of a render system issue, or block system, than just poll module.
The same problem applies to any customised block [or any content] for anonymous users, eg Ubercart's shopping cart block.
In that case, the approach taken when page caching is enabled,
is to provide a static text block for anonymous users when browsing around the site.
Shopping cart pages are excluded from the page cache altogether, so a customised block can be shown on these pages.
We could take a similar approach here.
If page caching is enabled, provide static text linking to the most recent poll node [rather that the actual form].
The anonymous user can then proceed to the poll node, which is set not to cache, and can vote and get instant feedback [as they can when page caching isn't enabled.]
For bonus progressive enhancement, via some javascript magic.
Place the form in the block, replacing the static text.
Capture the vote, and display the result.
Store the result in a cookie, and use that information to update the poll on subsequent pageviews by that anonymous users.
Comment #33
alanburke commentedI just noticed that the comment at #19 describes exactly what I suggest,
but requires some simple site configuration and an extra module, rather than being default behaviour.
Comment #34
c960657 commentedThe page cache in D7 is bypassed if an anonymous user has a non-empty $_SESSION, so I think it should be sufficient to set a dummy session variable upon voting. Unfortunately this prevents the user from taking advantage of the page cache for all pages, but I guess this is a price you have to pay.
Comment #35
c960657 commentedThis writes the votes of anonymous users to $_SESSION. In addition to solving the page cache issue, it also has the nice side-effect that anonymous users can only their own vote and not the votes of other users on the same network (with same external IP address).
Anonymous users can then only change their vote within the current session, though, but I think it is better to restrict the canceling of votes to a single session rather than to allow anonymous users on the same network to delete each others votes.
Comment #36
moshe weitzman commentedAnother inspired solution by c960657. This was a long standing, difficult problem. Kudos.
Comment #37
realityloop commented#35: poll-cache-anonymous-1.patch queued for re-testing.
Comment #39
c960657 commentedReroll.
Comment #40
jikishin commentedCode reviewed and passes tests.
Comment #41
dries commentedCommitted to CVS HEAD. Thanks!