Skip to content

Commit b6dace3

Browse files
Francisco Miguel Bietedenji
authored andcommitted
feat(purge all): Include option to purge all the cached files
This option can be slow if a lot of content is cached, or if the storage used for the cache is slow. But you really should be using RAM as your cache storage. Signed-off-by: Francisco Miguel Biete <[email protected]> Signed-off-by: Francisco Miguel Biete <[email protected]> Resolved FRiCKLE#33 Resolved FRiCKLE#35
1 parent a22e6bd commit b6dace3

File tree

3 files changed

+282
-28
lines changed

3 files changed

+282
-28
lines changed

README.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Configuration directives (same location syntax)
1919
===============================================
2020
fastcgi_cache_purge
2121
-------------------
22-
* **syntax**: `fastcgi_cache_purge on|off|<method> [from all|<ip> [.. <ip>]]`
22+
* **syntax**: `fastcgi_cache_purge on|off|<method> [purge_all] [from all|<ip> [.. <ip>]]`
2323
* **default**: `none`
2424
* **context**: `http`, `server`, `location`
2525

@@ -28,7 +28,7 @@ Allow purging of selected pages from `FastCGI`'s cache.
2828

2929
proxy_cache_purge
3030
-----------------
31-
* **syntax**: `proxy_cache_purge on|off|<method> [from all|<ip> [.. <ip>]]`
31+
* **syntax**: `proxy_cache_purge on|off|<method> [purge_all] [from all|<ip> [.. <ip>]]`
3232
* **default**: `none`
3333
* **context**: `http`, `server`, `location`
3434

@@ -37,7 +37,7 @@ Allow purging of selected pages from `proxy`'s cache.
3737

3838
scgi_cache_purge
3939
----------------
40-
* **syntax**: `scgi_cache_purge on|off|<method> [from all|<ip> [.. <ip>]]`
40+
* **syntax**: `scgi_cache_purge on|off|<method> [purge_all] [from all|<ip> [.. <ip>]]`
4141
* **default**: `none`
4242
* **context**: `http`, `server`, `location`
4343

@@ -46,7 +46,7 @@ Allow purging of selected pages from `SCGI`'s cache.
4646

4747
uwsgi_cache_purge
4848
-----------------
49-
* **syntax**: `uwsgi_cache_purge on|off|<method> [from all|<ip> [.. <ip>]]`
49+
* **syntax**: `uwsgi_cache_purge on|off|<method> [purge_all] [from all|<ip> [.. <ip>]]`
5050
* **default**: `none`
5151
* **context**: `http`, `server`, `location`
5252

@@ -107,6 +107,22 @@ Sample configuration (same location syntax)
107107
}
108108

109109

110+
Sample configuration (same location syntax - purge all cached files)
111+
====================================================================
112+
http {
113+
proxy_cache_path /tmp/cache keys_zone=tmpcache:10m;
114+
115+
server {
116+
location / {
117+
proxy_pass http://127.0.0.1:8000;
118+
proxy_cache tmpcache;
119+
proxy_cache_key $uri$is_args$args;
120+
proxy_cache_purge PURGE purge_all from 127.0.0.1;
121+
}
122+
}
123+
}
124+
125+
110126
Sample configuration (separate location syntax)
111127
===============================================
112128
http {

ngx_cache_purge_module.c

Lines changed: 122 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
typedef struct {
4444
ngx_flag_t enable;
4545
ngx_str_t method;
46+
ngx_flag_t purge_all;
4647
ngx_array_t *access; /* array of ngx_in_cidr_t */
4748
ngx_array_t *access6; /* array of ngx_in6_cidr_t */
4849
} ngx_http_cache_purge_conf_t;
@@ -90,6 +91,11 @@ char *ngx_http_uwsgi_cache_purge_conf(ngx_conf_t *cf,
9091
ngx_int_t ngx_http_uwsgi_cache_purge_handler(ngx_http_request_t *r);
9192
# endif /* NGX_HTTP_UWSGI */
9293

94+
static ngx_int_t
95+
ngx_http_purge_file_cache_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path);
96+
static ngx_int_t
97+
ngx_http_purge_file_cache_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path);
98+
9399
ngx_int_t ngx_http_cache_purge_access_handler(ngx_http_request_t *r);
94100
ngx_int_t ngx_http_cache_purge_access(ngx_array_t *a, ngx_array_t *a6,
95101
struct sockaddr *s);
@@ -105,6 +111,9 @@ void ngx_http_cache_purge_handler(ngx_http_request_t *r);
105111

106112
ngx_int_t ngx_http_file_cache_purge(ngx_http_request_t *r);
107113

114+
115+
void ngx_http_cache_purge_all(ngx_http_request_t *r, ngx_http_file_cache_t *cache);
116+
108117
char *ngx_http_cache_purge_conf(ngx_conf_t *cf,
109118
ngx_http_cache_purge_conf_t *cpcf);
110119

@@ -378,11 +387,12 @@ ngx_http_fastcgi_cache_purge_conf(ngx_conf_t *cf, ngx_command_t *cmd,
378387
ngx_int_t
379388
ngx_http_fastcgi_cache_purge_handler(ngx_http_request_t *r)
380389
{
381-
ngx_http_file_cache_t *cache;
382-
ngx_http_fastcgi_loc_conf_t *flcf;
390+
ngx_http_file_cache_t *cache;
391+
ngx_http_fastcgi_loc_conf_t *flcf;
392+
ngx_http_cache_purge_loc_conf_t *cplcf;
383393
# if (nginx_version >= 1007009)
384-
ngx_http_fastcgi_main_conf_t *fmcf;
385-
ngx_int_t rc;
394+
ngx_http_fastcgi_main_conf_t *fmcf;
395+
ngx_int_t rc;
386396
# endif /* nginx_version >= 1007009 */
387397

388398
if (ngx_http_upstream_create(r) != NGX_OK) {
@@ -414,6 +424,12 @@ ngx_http_fastcgi_cache_purge_handler(ngx_http_request_t *r)
414424
return NGX_HTTP_INTERNAL_SERVER_ERROR;
415425
}
416426

427+
// Purge-all option
428+
cplcf = ngx_http_get_module_loc_conf(r, ngx_http_cache_purge_module);
429+
if (cplcf->conf->purge_all) {
430+
ngx_http_cache_purge_all(r, cache);
431+
}
432+
417433
# if (nginx_version >= 8011)
418434
r->main->count++;
419435
# endif
@@ -649,11 +665,12 @@ ngx_http_proxy_cache_purge_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
649665
ngx_int_t
650666
ngx_http_proxy_cache_purge_handler(ngx_http_request_t *r)
651667
{
652-
ngx_http_file_cache_t *cache;
653-
ngx_http_proxy_loc_conf_t *plcf;
668+
ngx_http_file_cache_t *cache;
669+
ngx_http_proxy_loc_conf_t *plcf;
670+
ngx_http_cache_purge_loc_conf_t *cplcf;
654671
# if (nginx_version >= 1007009)
655-
ngx_http_proxy_main_conf_t *pmcf;
656-
ngx_int_t rc;
672+
ngx_http_proxy_main_conf_t *pmcf;
673+
ngx_int_t rc;
657674
# endif /* nginx_version >= 1007009 */
658675

659676
if (ngx_http_upstream_create(r) != NGX_OK) {
@@ -685,6 +702,12 @@ ngx_http_proxy_cache_purge_handler(ngx_http_request_t *r)
685702
return NGX_HTTP_INTERNAL_SERVER_ERROR;
686703
}
687704

705+
// Purge-all option
706+
cplcf = ngx_http_get_module_loc_conf(r, ngx_http_cache_purge_module);
707+
if (cplcf->conf->purge_all) {
708+
ngx_http_cache_purge_all(r, cache);
709+
}
710+
688711
# if (nginx_version >= 8011)
689712
r->main->count++;
690713
# endif
@@ -862,11 +885,12 @@ ngx_http_scgi_cache_purge_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
862885
ngx_int_t
863886
ngx_http_scgi_cache_purge_handler(ngx_http_request_t *r)
864887
{
865-
ngx_http_file_cache_t *cache;
866-
ngx_http_scgi_loc_conf_t *slcf;
888+
ngx_http_file_cache_t *cache;
889+
ngx_http_scgi_loc_conf_t *slcf;
890+
ngx_http_cache_purge_loc_conf_t *cplcf;
867891
# if (nginx_version >= 1007009)
868-
ngx_http_scgi_main_conf_t *smcf;
869-
ngx_int_t rc;
892+
ngx_http_scgi_main_conf_t *smcf;
893+
ngx_int_t rc;
870894
# endif /* nginx_version >= 1007009 */
871895

872896
if (ngx_http_upstream_create(r) != NGX_OK) {
@@ -898,6 +922,12 @@ ngx_http_scgi_cache_purge_handler(ngx_http_request_t *r)
898922
return NGX_HTTP_INTERNAL_SERVER_ERROR;
899923
}
900924

925+
// Purge-all option
926+
cplcf = ngx_http_get_module_loc_conf(r, ngx_http_cache_purge_module);
927+
if (cplcf->conf->purge_all) {
928+
ngx_http_cache_purge_all(r, cache);
929+
}
930+
901931
# if (nginx_version >= 8011)
902932
r->main->count++;
903933
# endif
@@ -1098,11 +1128,12 @@ ngx_http_uwsgi_cache_purge_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
10981128
ngx_int_t
10991129
ngx_http_uwsgi_cache_purge_handler(ngx_http_request_t *r)
11001130
{
1101-
ngx_http_file_cache_t *cache;
1102-
ngx_http_uwsgi_loc_conf_t *ulcf;
1131+
ngx_http_file_cache_t *cache;
1132+
ngx_http_uwsgi_loc_conf_t *ulcf;
1133+
ngx_http_cache_purge_loc_conf_t *cplcf;
11031134
# if (nginx_version >= 1007009)
1104-
ngx_http_uwsgi_main_conf_t *umcf;
1105-
ngx_int_t rc;
1135+
ngx_http_uwsgi_main_conf_t *umcf;
1136+
ngx_int_t rc;
11061137
# endif /* nginx_version >= 1007009 */
11071138

11081139
if (ngx_http_upstream_create(r) != NGX_OK) {
@@ -1134,6 +1165,12 @@ ngx_http_uwsgi_cache_purge_handler(ngx_http_request_t *r)
11341165
return NGX_HTTP_INTERNAL_SERVER_ERROR;
11351166
}
11361167

1168+
// Purge-all option
1169+
cplcf = ngx_http_get_module_loc_conf(r, ngx_http_cache_purge_module);
1170+
if (cplcf->conf->purge_all) {
1171+
ngx_http_cache_purge_all(r, cache);
1172+
}
1173+
11371174
# if (nginx_version >= 8011)
11381175
r->main->count++;
11391176
# endif
@@ -1144,6 +1181,27 @@ ngx_http_uwsgi_cache_purge_handler(ngx_http_request_t *r)
11441181
}
11451182
# endif /* NGX_HTTP_UWSGI */
11461183

1184+
1185+
static ngx_int_t
1186+
ngx_http_purge_file_cache_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path)
1187+
{
1188+
return NGX_OK;
1189+
}
1190+
1191+
static ngx_int_t
1192+
ngx_http_purge_file_cache_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path)
1193+
{
1194+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
1195+
"http file cache delete: \"%s\"", path->data);
1196+
1197+
if (ngx_delete_file(path->data) == NGX_FILE_ERROR) {
1198+
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
1199+
ngx_delete_file_n " \"%s\" failed", path->data);
1200+
}
1201+
1202+
return NGX_OK;
1203+
}
1204+
11471205
ngx_int_t
11481206
ngx_http_cache_purge_access_handler(ngx_http_request_t *r)
11491207
{
@@ -1401,6 +1459,7 @@ ngx_http_cache_purge_init(ngx_http_request_t *r, ngx_http_file_cache_t *cache,
14011459
void
14021460
ngx_http_cache_purge_handler(ngx_http_request_t *r)
14031461
{
1462+
ngx_http_cache_purge_loc_conf_t *cplcf;
14041463
ngx_int_t rc;
14051464

14061465
# if (NGX_HAVE_FILE_AIO)
@@ -1409,11 +1468,17 @@ ngx_http_cache_purge_handler(ngx_http_request_t *r)
14091468
}
14101469
# endif
14111470

1412-
rc = ngx_http_file_cache_purge(r);
1471+
cplcf = ngx_http_get_module_loc_conf(r, ngx_http_cache_purge_module);
1472+
if (cplcf->conf->purge_all) {
1473+
rc = NGX_OK;
1474+
}
1475+
else {
1476+
rc = ngx_http_file_cache_purge(r);
14131477

1414-
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1478+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
14151479
"http file cache purge: %i, \"%s\"",
14161480
rc, r->cache->file.name.data);
1481+
}
14171482

14181483
switch (rc) {
14191484
case NGX_OK:
@@ -1499,6 +1564,27 @@ ngx_http_file_cache_purge(ngx_http_request_t *r)
14991564
return NGX_OK;
15001565
}
15011566

1567+
1568+
void
1569+
ngx_http_cache_purge_all(ngx_http_request_t *r, ngx_http_file_cache_t *cache) {
1570+
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1571+
"purge_all http in %s",
1572+
cache->path->name.data);
1573+
1574+
// Walk the tree and remove all the files
1575+
ngx_tree_ctx_t tree;
1576+
tree.init_handler = NULL;
1577+
tree.file_handler = ngx_http_purge_file_cache_delete_file;
1578+
tree.pre_tree_handler = ngx_http_purge_file_cache_noop;
1579+
tree.post_tree_handler = ngx_http_purge_file_cache_noop;
1580+
tree.spec_handler = ngx_http_purge_file_cache_noop;
1581+
tree.data = cache;
1582+
tree.alloc = 0;
1583+
tree.log = ngx_cycle->log;
1584+
1585+
ngx_walk_tree(&tree, &cache->path->name);
1586+
}
1587+
15021588
char *
15031589
ngx_http_cache_purge_conf(ngx_conf_t *cf, ngx_http_cache_purge_conf_t *cpcf)
15041590
{
@@ -1510,7 +1596,11 @@ ngx_http_cache_purge_conf(ngx_conf_t *cf, ngx_http_cache_purge_conf_t *cpcf)
15101596
ngx_str_t *value;
15111597
ngx_int_t rc;
15121598
ngx_uint_t i;
1599+
ngx_uint_t from_position;
15131600

1601+
from_position = 2;
1602+
1603+
// xxx_cache_purge on|off|<method> [purge_all] [from all|<ip> [.. <ip>]]
15141604
value = cf->args->elts;
15151605

15161606
if (ngx_strcmp(value[1].data, "off") == 0) {
@@ -1529,20 +1619,27 @@ ngx_http_cache_purge_conf(ngx_conf_t *cf, ngx_http_cache_purge_conf_t *cpcf)
15291619
return NGX_CONF_OK;
15301620
}
15311621

1622+
// We will purge all the keys
1623+
if (ngx_strcmp(value[from_position].data, "purge_all") == 0) {
1624+
cpcf->purge_all = 1;
1625+
from_position++;
1626+
}
1627+
1628+
15321629
/* sanity check */
1533-
if (ngx_strcmp(value[2].data, "from") != 0) {
1630+
if (ngx_strcmp(value[from_position].data, "from") != 0) {
15341631
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
15351632
"invalid parameter \"%V\", expected"
1536-
" \"from\" keyword", &value[2]);
1633+
" \"from\" keyword", &value[from_position]);
15371634
return NGX_CONF_ERROR;
15381635
}
15391636

1540-
if (ngx_strcmp(value[3].data, "all") == 0) {
1637+
if (ngx_strcmp(value[from_position + 1].data, "all") == 0) {
15411638
cpcf->enable = 1;
15421639
return NGX_CONF_OK;
15431640
}
15441641

1545-
for (i = 3; i < cf->args->nelts; i++) {
1642+
for (i = (from_position + 1); i < cf->args->nelts; i++) {
15461643
rc = ngx_ptocidr(&value[i], &cidr);
15471644

15481645
if (rc == NGX_ERROR) {
@@ -1560,7 +1657,7 @@ ngx_http_cache_purge_conf(ngx_conf_t *cf, ngx_http_cache_purge_conf_t *cpcf)
15601657
switch (cidr.family) {
15611658
case AF_INET:
15621659
if (cpcf->access == NULL) {
1563-
cpcf->access = ngx_array_create(cf->pool, cf->args->nelts - 3,
1660+
cpcf->access = ngx_array_create(cf->pool, cf->args->nelts - (from_position + 1),
15641661
sizeof(ngx_in_cidr_t));
15651662
if (cpcf->access == NULL) {
15661663
return NGX_CONF_ERROR;
@@ -1580,7 +1677,7 @@ ngx_http_cache_purge_conf(ngx_conf_t *cf, ngx_http_cache_purge_conf_t *cpcf)
15801677
# if (NGX_HAVE_INET6)
15811678
case AF_INET6:
15821679
if (cpcf->access6 == NULL) {
1583-
cpcf->access6 = ngx_array_create(cf->pool, cf->args->nelts - 3,
1680+
cpcf->access6 = ngx_array_create(cf->pool, cf->args->nelts - (from_position + 1),
15841681
sizeof(ngx_in6_cidr_t));
15851682
if (cpcf->access6 == NULL) {
15861683
return NGX_CONF_ERROR;
@@ -1613,6 +1710,7 @@ ngx_http_cache_purge_merge_conf(ngx_http_cache_purge_conf_t *conf,
16131710
if (prev->enable == 1) {
16141711
conf->enable = prev->enable;
16151712
conf->method = prev->method;
1713+
conf->purge_all = prev->purge_all;
16161714
conf->access = prev->access;
16171715
conf->access6 = prev->access6;
16181716

0 commit comments

Comments
 (0)