it('causes a queue to be created the first time it\'s used', () => { expect(RelayTaskQueue.mock.instances.length).toBe(0); RelayTaskScheduler.enqueue(() => {}); expect(RelayTaskQueue.mock.instances.length).toBe(1); expect(RelayTaskQueue.prototype.constructor).toBeCalledWith(undefined); RelayTaskScheduler.enqueue(() => {}); expect(RelayTaskQueue.mock.instances.length).toBe(1); });
const runIteration = () => { // TODO: #9366746: integrate RelayRenderer/Container with GC hold warning( !pendingQueryTracker.hasPendingQueries(), 'RelayGarbageCollection: GC is executing during a fetch, but the ' + 'pending query may rely on data that is collected.' ); let iterations = 0; let hasNext = true; while (hasNext && (_stepLength < 0 || iterations < _stepLength)) { hasNext = run(); iterations++; } // This is effectively a (possibly async) `while` loop if (hasNext) { RelayTaskScheduler.enqueue(runIteration); } };
_handleSubtractedQuerySuccess( subtractedQuery: RelayQuery.Root, result: QueryResult ): void { this._fetchedSubtractedQuery = true; RelayTaskScheduler.enqueue(() => { var response = result.response; invariant( response && typeof response === 'object', 'RelayPendingQueryTracker: Expected response to be an object, got ' + '`%s`.', response ? typeof response : response ); this._storeData.handleQueryPayload( subtractedQuery, response, this._forceIndex ); }).done( this._markSubtractedQueryAsResolved.bind(this), this._markAsRejected.bind(this) ); }
function runQueries( storeData: RelayStoreData, queries: Array<RelayQuery.Root>, callback: ReadyStateChangeCallback, fetchMode: FetchMode, profiler: RelayProfileHandler ): Abortable { const readyState = new RelayReadyState(callback); var remainingFetchMap: {[queryID: string]: PendingFetch} = {}; var remainingRequiredFetchMap: {[queryID: string]: PendingFetch} = {}; function onResolved(pendingFetch: PendingFetch) { var pendingQuery = pendingFetch.getQuery(); var pendingQueryID = pendingQuery.getID(); delete remainingFetchMap[pendingQueryID]; if (!pendingQuery.isDeferred()) { delete remainingRequiredFetchMap[pendingQueryID]; } if (hasItems(remainingRequiredFetchMap)) { return; } if (someObject(remainingFetchMap, query => query.isResolvable())) { // The other resolvable query will resolve imminently and call // `readyState.update` instead. return; } if (hasItems(remainingFetchMap)) { readyState.update({done: false, ready: true, stale: false}); } else { readyState.update({done: true, ready: true, stale: false}); } } function onRejected(pendingFetch: PendingFetch, error: Error) { readyState.update({error}); var pendingQuery = pendingFetch.getQuery(); var pendingQueryID = pendingQuery.getID(); delete remainingFetchMap[pendingQueryID]; if (!pendingQuery.isDeferred()) { delete remainingRequiredFetchMap[pendingQueryID]; } } function canResolve(fetch: PendingFetch): boolean { return checkRelayQueryData( storeData.getQueuedStore(), fetch.getQuery() ); } RelayTaskScheduler.enqueue(() => { var forceIndex = fetchMode === RelayFetchMode.REFETCH ? generateForceIndex() : null; splitAndFlattenQueries(queries).forEach(query => { var pendingFetch = storeData.getPendingQueryTracker().add( {query, fetchMode, forceIndex, storeData} ); var queryID = query.getID(); remainingFetchMap[queryID] = pendingFetch; if (!query.isDeferred()) { remainingRequiredFetchMap[queryID] = pendingFetch; } pendingFetch.getResolvedPromise().then( onResolved.bind(null, pendingFetch), onRejected.bind(null, pendingFetch) ); }); if (!hasItems(remainingFetchMap)) { readyState.update({done: true, ready: true}); } else { if (!hasItems(remainingRequiredFetchMap)) { readyState.update({ready: true}); } else { readyState.update({ready: false}); resolveImmediate(() => { if (storeData.hasCacheManager()) { var requiredQueryMap = mapObject( remainingRequiredFetchMap, value => value.getQuery() ); storeData.readFromDiskCache(requiredQueryMap, { onSuccess: () => { if (hasItems(remainingRequiredFetchMap)) { readyState.update({ready: true, stale: true}); } }, }); } else { if (everyObject(remainingRequiredFetchMap, canResolve)) { if (hasItems(remainingRequiredFetchMap)) { readyState.update({ready: true, stale: true}); } } } }); } } // Stop profiling when queries have been sent to the network layer. profiler.stop(); }).done(); return { abort(): void { readyState.update({aborted: true}); }, }; }
it('uses the injected scheduler to schedule tasks', () => { jest.dontMock('RelayTaskQueue'); const mockTask = () => {}; RelayTaskScheduler.enqueue(mockTask); expect(mockScheduler).toBeCalled(); });