Hi,

Varnish has a limit of 8192 characters per line (so per-command in our case). You are supposed to be able to raise this with param.set cli_buffer [x], but this doesn't seem to work. https://www.varnish-cache.org/trac/ticket/772 seems to state that longer commands are only allowed in authenticated mode with the new heredoc syntax, raising the question of what the cli_buffer param actually does...

Anyway, I've had trouble with the expire module purging an entire menu with hundreds of nodes in it, and Varnish hanging up the socket after more than 8192 bytes of regex were pushed at it in a single command.

I've created a patch that causes varnish_expire_cache() to batch the varnish_purge() commands into regexes not too much longer than 7500 bytes each to prevent this problem. You do end up with multiple bans in your ban list if it's there's a lot of paths, but at least it's a compatible way to prevent hitting the command length limit.

Unfortunately this only protects in the case of Expire module usage. Direct calls into varnish_purge() may still fail if they're too long, as the regex is compiled elsewhere.

Hope this helps someone!

Comments

fabsor’s picture

We have support for issuing multiple commands within one connection, maybe we could use that somehow? I guess we like this to work everywhere, not just only for expire.

neilnz’s picture

Sure, that would be nice, but would require refactoring the building of regexes to somewhere further down the chain. Maybe make varnish_purge() optionally take an array in place of $pattern, and build the regexp itself, taking care to limit it appropriately.

The other option would be to parse out the regexp in varnish_purge() and split it there, but that's really ugly.

I've noticed that my patch doesn't always solve the problem where there are a lot of short paths, as the 3 characters added by the regexp in between each path are not counted. When you have hundreds of paths, the bytes taken up by these regexp characters become significant and push the string over the limit again. I've got a revised patch to fix that up, but maybe we should have a look at implementing it down in varnish_purge() instead?

Happy to have a go at a patch along those lines if you like?

fabsor’s picture

Status: Needs review » Needs work

I think your solution sounds like a good one. Let's try to get that logic into varnish_purge. I'm putting this into needs work for now, thanks for working on this!

Eugene Fidelin’s picture

StatusFileSize
new1.62 KB

I propose another solution.

In varnish_expire_cache () we need to divide $paths array into chunks by 30 items
In this case we will exceed the maximum length of command (8000 characters) only if all urдs has length more than 250 characters - this is unlikely.

Of course user can specify other chunk size in settings

neilnz’s picture

Status: Needs work » Needs review
StatusFileSize
new2.3 KB

Here is an improved patch that adds a varnish_purge_paths() function that takes care of building the regex. varnish_expire_cache() now calls this, rather than varnish_purge() directly. The varnish_purge() function still works the same way, so won't break any other modules calling into this directly.

neilnz’s picture

StatusFileSize
new2.72 KB

... and I just realised that the Drush command calls the varnish_expire_cache() hook directly. I've changed it to call varnish_purge_paths() instead.

Here's an updated patch for this.

pjcdawkins’s picture

Version: 6.x-1.x-dev » 7.x-1.x-dev
StatusFileSize
new2.23 KB

Reroll for D7.

millenniumtree’s picture

Glad to see this addressed - just had a problem with our very large multi-domain site. One particular page was expiring over 11,000 individual URLs.
Must-have for the D6 release!

pjcdawkins’s picture

StatusFileSize
new3.88 KB

Rerolled for latest -dev / -beta2.

patrick_durold’s picture

StatusFileSize
new2.23 KB

#9 will not apply to varnish 7.x-1.0-beta2 and contains mostly idempotent hunks anyway. Patch redone and tested with beta2.

vincenzo’s picture

Status: Needs review » Reviewed & tested by the community

Patch #10 works beautifully for me. I am keen to see this merged in.

pjcdawkins’s picture

Yes patch #10 works well.

imclean’s picture

Patch in #6 resolved the issue for me with 6.x-1.x-dev.

vincenzo’s picture

Any chance we are going to see this merged in? Please.
(#10 works flawlessly)

JeremyFrench’s picture

JeremyFrench’s picture

Issue summary: View changes
Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

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

brettdonohoo’s picture

I think this problem re-emerged after this patch.

http://cgit.drupalcode.org/varnish/commit/?id=6412c501e71cbaf39316ca3ee3...

I'm getting this same error in 7.x-1.0-beta3.

brettdonohoo’s picture

Status: Closed (fixed) » Needs work
brettdonohoo’s picture

StatusFileSize
new758 bytes

Reroll for beta3.

brettdonohoo’s picture

Status: Needs work » Needs review
jwintx’s picture

Patch #20 resolved the issue for me in beta3

das-peter’s picture

Status: Needs review » Reviewed & tested by the community
StatusFileSize
new765 bytes

Re-rolled for 7.x-1.x-dev, seems to work as intended and mainly re-introduces a lost approach.
So I'd say RTBC.

misc’s picture

Status: Reviewed & tested by the community » Fixed

Thanks. Pushed to latest dev, will be in beta5.

  • MiSc committed 90d3247 on 7.x-1.x authored by das-peter
    Issue #1481136 by neilnz, pjcdawkins, brettdonohoo, Eugene Fidelin,...
misc’s picture

Correction - will be in 7-x.1.1

Status: Fixed » Closed (fixed)

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