public cacheImage$()

in src/graph/GraphService.ts [195:404]


    public cacheImage$(id: string): Observable<Image> {
        const firstGraphSubject$: Subject<Graph> = new Subject<Graph>();

        this._firstGraphSubjects$.push(firstGraphSubject$);

        const firstGraph$: Observable<Graph> = firstGraphSubject$.pipe(
            publishReplay(1),
            refCount());

        const image$: Observable<Image> = firstGraph$.pipe(
            map(
                (graph: Graph): Image => {
                    return graph.getNode(id);
                }),
            mergeMap(
                (image: Image): Observable<Image> => {
                    return image.assetsCached ?
                        observableOf(image) :
                        image.cacheAssets$();
                }),
            publishReplay(1),
            refCount());

        image$.subscribe(
            undefined,
            (error: Error): void => {
                console.error(`Failed to cache image (${id}).`, error);
            });

        let initializeCacheSubscription: Subscription;
        initializeCacheSubscription = this._graph$.pipe(
            first(),
            mergeMap(
                (graph: Graph): Observable<Graph> => {
                    if (graph.isCachingFull(id) || !graph.hasNode(id)) {
                        return graph.cacheFull$(id);
                    }

                    if (graph.isCachingFill(id) || !graph.getNode(id).complete) {
                        return graph.cacheFill$(id);
                    }

                    return observableOf<Graph>(graph);
                }),
            tap(
                (graph: Graph): void => {
                    if (!graph.hasNode(id)) {
                        throw new GraphMapillaryError(`Failed to cache image (${id})`);
                    }

                    if (!graph.hasInitializedCache(id)) {
                        graph.initializeCache(id);
                    }
                }),
            finalize(
                (): void => {
                    if (initializeCacheSubscription == null) {
                        return;
                    }

                    this._removeFromArray(initializeCacheSubscription, this._initializeCacheSubscriptions);
                    this._removeFromArray(firstGraphSubject$, this._firstGraphSubjects$);
                }))
            .subscribe(
                (graph: Graph): void => {
                    firstGraphSubject$.next(graph);
                    firstGraphSubject$.complete();
                },
                (error: Error): void => {
                    firstGraphSubject$.error(error);
                });

        if (!initializeCacheSubscription.closed) {
            this._initializeCacheSubscriptions.push(initializeCacheSubscription);
        }

        const graphSequence$: Observable<Graph> = firstGraph$.pipe(
            catchError(
                (): Observable<Graph> => {
                    return observableEmpty();
                }),
            mergeMap(
                (graph: Graph): Observable<Graph> => {
                    if (graph.isCachingNodeSequence(id) || !graph.hasNodeSequence(id)) {
                        return graph.cacheNodeSequence$(id);
                    }

                    return observableOf<Graph>(graph);
                }),
            publishReplay(1),
            refCount());

        let sequenceSubscription: Subscription;
        sequenceSubscription = graphSequence$.pipe(
            tap(
                (graph: Graph): void => {
                    if (!graph.getNode(id).sequenceEdges.cached) {
                        graph.cacheSequenceEdges(id);
                    }
                }),
            finalize(
                (): void => {
                    if (sequenceSubscription == null) {
                        return;
                    }

                    this._removeFromArray(sequenceSubscription, this._sequenceSubscriptions);
                }))
            .subscribe(
                (): void => { return; },
                (error: Error): void => {
                    console.error(`Failed to cache sequence edges (${id}).`, error);
                });

        if (!sequenceSubscription.closed) {
            this._sequenceSubscriptions.push(sequenceSubscription);
        }

        if (this._graphMode === GraphMode.Spatial) {
            let spatialSubscription: Subscription;
            spatialSubscription = firstGraph$.pipe(
                catchError(
                    (): Observable<Graph> => {
                        return observableEmpty();
                    }),
                expand(
                    (graph: Graph): Observable<Graph> => {
                        if (graph.hasTiles(id)) {
                            return observableEmpty();
                        }

                        return observableFrom(graph.cacheTiles$(id)).pipe(
                            mergeMap(
                                (graph$: Observable<Graph>): Observable<Graph> => {
                                    return graph$.pipe(
                                        mergeMap(
                                            (g: Graph): Observable<Graph> => {
                                                if (g.isCachingTiles(id)) {
                                                    return observableEmpty();
                                                }

                                                return observableOf<Graph>(g);
                                            }),
                                        catchError(
                                            (error: Error): Observable<Graph> => {
                                                console.error(`Failed to cache tile data (${id}).`, error);

                                                return observableEmpty();
                                            }));
                                }));
                    }),
                takeLast(1),
                mergeMap(
                    (graph: Graph): Observable<Graph> => {
                        if (graph.hasSpatialArea(id)) {
                            return observableOf<Graph>(graph);
                        }

                        return observableFrom(graph.cacheSpatialArea$(id)).pipe(
                            mergeMap(
                                (graph$: Observable<Graph>): Observable<Graph> => {
                                    return graph$.pipe(
                                        catchError(
                                            (error: Error): Observable<Graph> => {
                                                console.error(`Failed to cache spatial images (${id}).`, error);

                                                return observableEmpty();
                                            }));
                                }));
                    }),
                takeLast(1),
                mergeMap(
                    (graph: Graph): Observable<Graph> => {
                        return graph.hasNodeSequence(id) ?
                            observableOf<Graph>(graph) :
                            graph.cacheNodeSequence$(id);
                    }),
                tap(
                    (graph: Graph): void => {
                        if (!graph.getNode(id).spatialEdges.cached) {
                            graph.cacheSpatialEdges(id);
                        }
                    }),
                finalize(
                    (): void => {
                        if (spatialSubscription == null) {
                            return;
                        }

                        this._removeFromArray(spatialSubscription, this._spatialSubscriptions);
                    }))
                .subscribe(
                    (): void => { return; },
                    (error: Error): void => {
                        const message =
                            `Failed to cache spatial edges (${id}).`;
                        console.error(message, error);
                    });

            if (!spatialSubscription.closed) {
                this._spatialSubscriptions.push(spatialSubscription);
            }
        }

        return image$.pipe(
            first(
                (image: Image): boolean => {
                    return image.assetsCached;
                }));
    }