1 | /*
|
2 | Copyright 2018 Google LLC
|
3 |
|
4 | Use of this source code is governed by an MIT-style
|
5 | license that can be found in the LICENSE file or at
|
6 | https://opensource.org/licenses/MIT.
|
7 | */
|
8 | import { assert } from 'workbox-core/_private/assert.js';
|
9 | import { QueueDb, } from './QueueDb.js';
|
10 | import '../_version.js';
|
11 | /**
|
12 | * A class to manage storing requests from a Queue in IndexedDB,
|
13 | * indexed by their queue name for easier access.
|
14 | *
|
15 | * Most developers will not need to access this class directly;
|
16 | * it is exposed for advanced use cases.
|
17 | */
|
18 | export class QueueStore {
|
19 | /**
|
20 | * Associates this instance with a Queue instance, so entries added can be
|
21 | * identified by their queue name.
|
22 | *
|
23 | * @param {string} queueName
|
24 | */
|
25 | constructor(queueName) {
|
26 | this._queueName = queueName;
|
27 | this._queueDb = new QueueDb();
|
28 | }
|
29 | /**
|
30 | * Append an entry last in the queue.
|
31 | *
|
32 | * @param {Object} entry
|
33 | * @param {Object} entry.requestData
|
34 | * @param {number} [entry.timestamp]
|
35 | * @param {Object} [entry.metadata]
|
36 | */
|
37 | async pushEntry(entry) {
|
38 | if (process.env.NODE_ENV !== 'production') {
|
39 | assert.isType(entry, 'object', {
|
40 | moduleName: 'workbox-background-sync',
|
41 | className: 'QueueStore',
|
42 | funcName: 'pushEntry',
|
43 | paramName: 'entry',
|
44 | });
|
45 | assert.isType(entry.requestData, 'object', {
|
46 | moduleName: 'workbox-background-sync',
|
47 | className: 'QueueStore',
|
48 | funcName: 'pushEntry',
|
49 | paramName: 'entry.requestData',
|
50 | });
|
51 | }
|
52 | // Don't specify an ID since one is automatically generated.
|
53 | delete entry.id;
|
54 | entry.queueName = this._queueName;
|
55 | await this._queueDb.addEntry(entry);
|
56 | }
|
57 | /**
|
58 | * Prepend an entry first in the queue.
|
59 | *
|
60 | * @param {Object} entry
|
61 | * @param {Object} entry.requestData
|
62 | * @param {number} [entry.timestamp]
|
63 | * @param {Object} [entry.metadata]
|
64 | */
|
65 | async unshiftEntry(entry) {
|
66 | if (process.env.NODE_ENV !== 'production') {
|
67 | assert.isType(entry, 'object', {
|
68 | moduleName: 'workbox-background-sync',
|
69 | className: 'QueueStore',
|
70 | funcName: 'unshiftEntry',
|
71 | paramName: 'entry',
|
72 | });
|
73 | assert.isType(entry.requestData, 'object', {
|
74 | moduleName: 'workbox-background-sync',
|
75 | className: 'QueueStore',
|
76 | funcName: 'unshiftEntry',
|
77 | paramName: 'entry.requestData',
|
78 | });
|
79 | }
|
80 | const firstId = await this._queueDb.getFirstEntryId();
|
81 | if (firstId) {
|
82 | // Pick an ID one less than the lowest ID in the object store.
|
83 | entry.id = firstId - 1;
|
84 | }
|
85 | else {
|
86 | // Otherwise let the auto-incrementor assign the ID.
|
87 | delete entry.id;
|
88 | }
|
89 | entry.queueName = this._queueName;
|
90 | await this._queueDb.addEntry(entry);
|
91 | }
|
92 | /**
|
93 | * Removes and returns the last entry in the queue matching the `queueName`.
|
94 | *
|
95 | * @return {Promise<QueueStoreEntry|undefined>}
|
96 | */
|
97 | async popEntry() {
|
98 | return this._removeEntry(await this._queueDb.getLastEntryByQueueName(this._queueName));
|
99 | }
|
100 | /**
|
101 | * Removes and returns the first entry in the queue matching the `queueName`.
|
102 | *
|
103 | * @return {Promise<QueueStoreEntry|undefined>}
|
104 | */
|
105 | async shiftEntry() {
|
106 | return this._removeEntry(await this._queueDb.getFirstEntryByQueueName(this._queueName));
|
107 | }
|
108 | /**
|
109 | * Returns all entries in the store matching the `queueName`.
|
110 | *
|
111 | * @param {Object} options See {@link workbox-background-sync.Queue~getAll}
|
112 | * @return {Promise<Array<Object>>}
|
113 | */
|
114 | async getAll() {
|
115 | return await this._queueDb.getAllEntriesByQueueName(this._queueName);
|
116 | }
|
117 | /**
|
118 | * Returns the number of entries in the store matching the `queueName`.
|
119 | *
|
120 | * @param {Object} options See {@link workbox-background-sync.Queue~size}
|
121 | * @return {Promise<number>}
|
122 | */
|
123 | async size() {
|
124 | return await this._queueDb.getEntryCountByQueueName(this._queueName);
|
125 | }
|
126 | /**
|
127 | * Deletes the entry for the given ID.
|
128 | *
|
129 | * WARNING: this method does not ensure the deleted entry belongs to this
|
130 | * queue (i.e. matches the `queueName`). But this limitation is acceptable
|
131 | * as this class is not publicly exposed. An additional check would make
|
132 | * this method slower than it needs to be.
|
133 | *
|
134 | * @param {number} id
|
135 | */
|
136 | async deleteEntry(id) {
|
137 | await this._queueDb.deleteEntry(id);
|
138 | }
|
139 | /**
|
140 | * Removes and returns the first or last entry in the queue (based on the
|
141 | * `direction` argument) matching the `queueName`.
|
142 | *
|
143 | * @return {Promise<QueueStoreEntry|undefined>}
|
144 | * @private
|
145 | */
|
146 | async _removeEntry(entry) {
|
147 | if (entry) {
|
148 | await this.deleteEntry(entry.id);
|
149 | }
|
150 | return entry;
|
151 | }
|
152 | }
|