| 133 | } |
| 134 | |
| 135 | async sync() { |
| 136 | let toast: Toast | null = null |
| 137 | |
| 138 | try { |
| 139 | const config = this.getConfig() |
| 140 | if (!config) { |
| 141 | this.log.info('Sync service not configured') |
| 142 | return |
| 143 | } |
| 144 | |
| 145 | toast = this.toasts.loading('Checking for links to sync…') |
| 146 | const links = await this.get<SyncLinkItem[]>('/links') |
| 147 | |
| 148 | this.log.debug('links', links) |
| 149 | |
| 150 | if (links.length === 0) { |
| 151 | toast.success('Sync complete!') |
| 152 | return |
| 153 | } |
| 154 | |
| 155 | const MAX_CONCURRENT_ITEMS = 8 |
| 156 | const PROCESS_TIMEOUT = 1000 * 15 // give each item max 15 seconds to process |
| 157 | |
| 158 | const processedItems: SyncLinkItem[] = [] |
| 159 | |
| 160 | this.log.debug('processing items:', links) |
| 161 | const queue = new PQueue({ |
| 162 | concurrency: MAX_CONCURRENT_ITEMS, |
| 163 | timeout: PROCESS_TIMEOUT, |
| 164 | autoStart: false |
| 165 | }) |
| 166 | |
| 167 | let count = 0 |
| 168 | |
| 169 | queue.on('completed', () => { |
| 170 | toast?.update({ |
| 171 | message: `Syncing links (${++count}/${links.length})…` |
| 172 | }) |
| 173 | }) |
| 174 | |
| 175 | links.forEach((link) => { |
| 176 | queue.add(async () => { |
| 177 | this.log.debug('processing item:', link) |
| 178 | const resource = await this.processLink(link) |
| 179 | this.log.debug('processed resource:', resource) |
| 180 | |
| 181 | if (resource) { |
| 182 | processedItems.push(link) |
| 183 | } |
| 184 | }) |
| 185 | }) |
| 186 | |
| 187 | queue.start() |
| 188 | |
| 189 | toast.update({ |
| 190 | message: `Syncing ${links.length} link${links.length > 1 ? 's' : ''}…` |
| 191 | }) |
| 192 | |