File size: 4,111 Bytes
979bf48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, /**
 * In the web server, there is currently no incremental cache provided and we
 * always SSR the page.
 */ "default", {
    enumerable: true,
    get: function() {
        return WebResponseCache;
    }
});
const _detachedpromise = require("../../lib/detached-promise");
class WebResponseCache {
    constructor(minimalMode){
        this.pendingResponses = new Map();
        // this is a hack to avoid Webpack knowing this is equal to this.minimalMode
        // because we replace this.minimalMode to true in production bundles.
        Object.assign(this, {
            minimalMode
        });
    }
    get(key, responseGenerator, context) {
        var _this_previousCacheItem;
        // ensure on-demand revalidate doesn't block normal requests
        const pendingResponseKey = key ? `${key}-${context.isOnDemandRevalidate ? '1' : '0'}` : null;
        const pendingResponse = pendingResponseKey ? this.pendingResponses.get(pendingResponseKey) : null;
        if (pendingResponse) {
            return pendingResponse;
        }
        const { promise, resolve: resolver, reject: rejecter } = new _detachedpromise.DetachedPromise();
        if (pendingResponseKey) {
            this.pendingResponses.set(pendingResponseKey, promise);
        }
        let hasResolved = false;
        const resolve = (cacheEntry)=>{
            if (pendingResponseKey) {
                // Ensure all reads from the cache get the latest value.
                this.pendingResponses.set(pendingResponseKey, Promise.resolve(cacheEntry));
            }
            if (!hasResolved) {
                hasResolved = true;
                resolver(cacheEntry);
            }
        };
        // we keep the previous cache entry around to leverage
        // when the incremental cache is disabled in minimal mode
        if (pendingResponseKey && this.minimalMode && ((_this_previousCacheItem = this.previousCacheItem) == null ? void 0 : _this_previousCacheItem.key) === pendingResponseKey && this.previousCacheItem.expiresAt > Date.now()) {
            resolve(this.previousCacheItem.entry);
            this.pendingResponses.delete(pendingResponseKey);
            return promise;
        }
        // We wait to do any async work until after we've added our promise to
        // `pendingResponses` to ensure that any any other calls will reuse the
        // same promise until we've fully finished our work.
        ;
        (async ()=>{
            try {
                const cacheEntry = await responseGenerator({
                    hasResolved
                });
                const resolveValue = cacheEntry === null ? null : {
                    ...cacheEntry,
                    isMiss: true
                };
                // for on-demand revalidate wait to resolve until cache is set
                if (!context.isOnDemandRevalidate) {
                    resolve(resolveValue);
                }
                if (key && cacheEntry && cacheEntry.cacheControl) {
                    this.previousCacheItem = {
                        key: pendingResponseKey || key,
                        entry: cacheEntry,
                        expiresAt: Date.now() + 1000
                    };
                } else {
                    this.previousCacheItem = undefined;
                }
                if (context.isOnDemandRevalidate) {
                    resolve(resolveValue);
                }
            } catch (err) {
                // while revalidating in the background we can't reject as
                // we already resolved the cache entry so log the error here
                if (hasResolved) {
                    console.error(err);
                } else {
                    rejecter(err);
                }
            } finally{
                if (pendingResponseKey) {
                    this.pendingResponses.delete(pendingResponseKey);
                }
            }
        })();
        return promise;
    }
}

//# sourceMappingURL=web.js.map