aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-06-05 10:05:49 +0200
committerChocobozzz <me@florianbigard.com>2023-06-05 10:05:49 +0200
commited14d1ebd7c8d9428ac58b3a6280e3df6686aec1 (patch)
treebf3caf6f5f9a46069b5080272fd427af3fbd6fbb /server
parent96290a6b78ce1ecba5f91faaa08cdd941331af4b (diff)
downloadPeerTube-ed14d1ebd7c8d9428ac58b3a6280e3df6686aec1.tar.gz
PeerTube-ed14d1ebd7c8d9428ac58b3a6280e3df6686aec1.tar.zst
PeerTube-ed14d1ebd7c8d9428ac58b3a6280e3df6686aec1.zip
Invalidate cache feed even after server restart
Diffstat (limited to 'server')
-rw-r--r--server/middlewares/cache/shared/api-cache.ts6
-rw-r--r--server/tests/feeds/feeds.ts110
2 files changed, 93 insertions, 23 deletions
diff --git a/server/middlewares/cache/shared/api-cache.ts b/server/middlewares/cache/shared/api-cache.ts
index c6197b972..b50b7dce4 100644
--- a/server/middlewares/cache/shared/api-cache.ts
+++ b/server/middlewares/cache/shared/api-cache.ts
@@ -35,7 +35,11 @@ export class ApiCache {
35 // Cache keys per group 35 // Cache keys per group
36 private groups: { [groupIndex: string]: string[] } = {} 36 private groups: { [groupIndex: string]: string[] } = {}
37 37
38 private readonly seed: number
39
38 constructor (options: APICacheOptions) { 40 constructor (options: APICacheOptions) {
41 this.seed = new Date().getTime()
42
39 this.options = { 43 this.options = {
40 headerBlacklist: [], 44 headerBlacklist: [],
41 excludeStatus: [], 45 excludeStatus: [],
@@ -88,7 +92,7 @@ export class ApiCache {
88 } 92 }
89 93
90 private getCacheKey (req: express.Request) { 94 private getCacheKey (req: express.Request) {
91 return Redis.Instance.getPrefix() + 'api-cache-' + req.originalUrl 95 return Redis.Instance.getPrefix() + 'api-cache-' + this.seed + '-' + req.originalUrl
92 } 96 }
93 97
94 private shouldCacheResponse (response: express.Response) { 98 private shouldCacheResponse (response: express.Response) {
diff --git a/server/tests/feeds/feeds.ts b/server/tests/feeds/feeds.ts
index 286c03596..8433c873e 100644
--- a/server/tests/feeds/feeds.ts
+++ b/server/tests/feeds/feeds.ts
@@ -14,6 +14,7 @@ import {
14 PluginsCommand, 14 PluginsCommand,
15 setAccessTokensToServers, 15 setAccessTokensToServers,
16 setDefaultChannelAvatar, 16 setDefaultChannelAvatar,
17 setDefaultVideoChannel,
17 stopFfmpeg, 18 stopFfmpeg,
18 waitJobs 19 waitJobs
19} from '@shared/server-commands' 20} from '@shared/server-commands'
@@ -53,6 +54,7 @@ describe('Test syndication feeds', () => {
53 54
54 await setAccessTokensToServers([ ...servers, serverHLSOnly ]) 55 await setAccessTokensToServers([ ...servers, serverHLSOnly ])
55 await setDefaultChannelAvatar(servers[0]) 56 await setDefaultChannelAvatar(servers[0])
57 await setDefaultVideoChannel(servers)
56 await doubleFollow(servers[0], servers[1]) 58 await doubleFollow(servers[0], servers[1])
57 59
58 await servers[0].config.enableLive({ allowReplay: false, transcoding: false }) 60 await servers[0].config.enableLive({ allowReplay: false, transcoding: false })
@@ -137,28 +139,6 @@ describe('Test syndication feeds', () => {
137 }) 139 })
138 }) 140 })
139 141
140 it('Should serve the endpoint as a cached request', async function () {
141 const res = await makeGetRequest({
142 url: servers[0].url,
143 path: '/feeds/videos.xml',
144 accept: 'application/xml',
145 expectedStatus: HttpStatusCode.OK_200
146 })
147
148 expect(res.headers['x-api-cache-cached']).to.equal('true')
149 })
150
151 it('Should not serve the endpoint as a cached request', async function () {
152 const res = await makeGetRequest({
153 url: servers[0].url,
154 path: '/feeds/videos.xml?v=186',
155 accept: 'application/xml',
156 expectedStatus: HttpStatusCode.OK_200
157 })
158
159 expect(res.headers['x-api-cache-cached']).to.not.exist
160 })
161
162 it('Should refuse to serve the endpoint without accept header', async function () { 142 it('Should refuse to serve the endpoint without accept header', async function () {
163 await makeGetRequest({ url: servers[0].url, path: '/feeds/videos.xml', expectedStatus: HttpStatusCode.NOT_ACCEPTABLE_406 }) 143 await makeGetRequest({ url: servers[0].url, path: '/feeds/videos.xml', expectedStatus: HttpStatusCode.NOT_ACCEPTABLE_406 })
164 }) 144 })
@@ -614,6 +594,92 @@ describe('Test syndication feeds', () => {
614 594
615 }) 595 })
616 596
597 describe('Cache', function () {
598 const uuids: string[] = []
599
600 function doPodcastRequest () {
601 return makeGetRequest({
602 url: servers[0].url,
603 path: '/feeds/podcast/videos.xml',
604 query: { videoChannelId: servers[0].store.channel.id },
605 accept: 'application/xml',
606 expectedStatus: HttpStatusCode.OK_200
607 })
608 }
609
610 function doVideosRequest (query: { [id: string]: string } = {}) {
611 return makeGetRequest({
612 url: servers[0].url,
613 path: '/feeds/videos.xml',
614 query,
615 accept: 'application/xml',
616 expectedStatus: HttpStatusCode.OK_200
617 })
618 }
619
620 before(async function () {
621 {
622 const { uuid } = await servers[0].videos.quickUpload({ name: 'cache 1' })
623 uuids.push(uuid)
624 }
625
626 {
627 const { uuid } = await servers[0].videos.quickUpload({ name: 'cache 2' })
628 uuids.push(uuid)
629 }
630 })
631
632 it('Should serve the videos endpoint as a cached request', async function () {
633 await doVideosRequest()
634
635 const res = await doVideosRequest()
636
637 expect(res.headers['x-api-cache-cached']).to.equal('true')
638 })
639
640 it('Should not serve the videos endpoint as a cached request', async function () {
641 const res = await doVideosRequest({ v: '186' })
642
643 expect(res.headers['x-api-cache-cached']).to.not.exist
644 })
645
646 it('Should invalidate the podcast feed cache after video deletion', async function () {
647 await doPodcastRequest()
648
649 {
650 const res = await doPodcastRequest()
651 expect(res.headers['x-api-cache-cached']).to.exist
652 }
653
654 await servers[0].videos.remove({ id: uuids[0] })
655
656 {
657 const res = await doPodcastRequest()
658 expect(res.headers['x-api-cache-cached']).to.not.exist
659 }
660 })
661
662 it('Should invalidate the podcast feed cache after video deletion, even after server restart', async function () {
663 this.timeout(120000)
664
665 await doPodcastRequest()
666
667 {
668 const res = await doPodcastRequest()
669 expect(res.headers['x-api-cache-cached']).to.exist
670 }
671
672 await servers[0].kill()
673 await servers[0].run()
674
675 await servers[0].videos.remove({ id: uuids[1] })
676
677 const res = await doPodcastRequest()
678 expect(res.headers['x-api-cache-cached']).to.not.exist
679 })
680
681 })
682
617 after(async function () { 683 after(async function () {
618 await servers[0].plugins.uninstall({ npmName: 'peertube-plugin-test-podcast-custom-tags' }) 684 await servers[0].plugins.uninstall({ npmName: 'peertube-plugin-test-podcast-custom-tags' })
619 685