Ejemplo n.º 1
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            Logger.LogInformation("Running OfflineCacheBackgroundTask.");

            using (IServiceScope scope = ScopeFactory.CreateScope())
            {
                TileCacheRepository  = scope.ServiceProvider.GetRequiredService <TileCacheRepository>();
                TileSourceRepository = scope.ServiceProvider.GetRequiredService <TileSourceRepository>();
                Mapper = scope.ServiceProvider.GetRequiredService <IMapper>();

                do
                {
                    TileCacheViewModel unfinishedTileCache =
                        Mapper.Map <TileCacheViewModel>(await TileCacheRepository.GetFirstUnfinishedTileCache());

                    if (unfinishedTileCache != null)
                    {
                        await TileCacheRepository.SetTileCacheStarted(unfinishedTileCache.TileCacheId);

                        TileCacheManager tileCacheManager = await CreateTileCacheManager(unfinishedTileCache.TileCacheId);

                        TilesCount = 0;

                        // Do not remove already downloaded tiles
                        ////tileService.ClearTiles();

                        try
                        {
                            Bounds bounds = GeometryHelper.ToBounds(unfinishedTileCache.Bbox);

                            TileSource tileSource = await TileSourceRepository.GetTileSourceWithId(unfinishedTileCache.TileSourceId);

                            TileRangeCalculator calculator = new TileRangeCalculator
                            {
                                ValidBounds    = GeometryHelper.ToBounds(tileSource.Bbox),
                                ValidZoomRange = new ZoomRange
                                {
                                    MinZoom = 0,
                                    MaxZoom = tileSource.ZoomLevelMax,
                                },
                            };

                            TileRangeCollection tiles = new TileRangeCollectionCalculator(calculator).GetTileRanges(bounds, new ZoomRange
                            {
                                MinZoom = unfinishedTileCache.ZoomLevelMin ?? 0,
                                MaxZoom = unfinishedTileCache.ZoomLevelMax,
                            });

                            TilesTotal = tiles.TilesTotal;

                            if (TilesTotal > 30000)
                            {
                                await TileCacheRepository.SetTileCacheError(unfinishedTileCache.TileCacheId);

                                throw new ArgumentException($"Tile cache exceeding the maximum number of 30000 tiles: {TilesTotal}.");
                            }

                            TileDownloader tileDownloader =
                                tileSource.AllowHiDefStitching ? new MergedTileDownloader() : new TileDownloader();
                            tileDownloader.TileServerUrls = tileSource.TileServerUrls.Select(x => x.Url).ToList();

                            await tileDownloader.Download(tiles, (zoomLevel, tileRow, tileColumn, tileData) =>
                            {
                                // Note that in the TMS tiling scheme, the Y axis is reversed from the "XYZ" coordinate system commonly used in the URLs
                                int mbtilesRow = (int)Math.Pow(2, zoomLevel) - 1 - tileRow;

                                lock (OfflineCacheBackgroundTask.lockObject)
                                {
                                    TilesCount++;
                                }

                                if (tileCacheManager.TryGetTile(tileColumn, mbtilesRow, zoomLevel) == null)
                                {
                                    tileCacheManager.SaveTile(zoomLevel, mbtilesRow, tileColumn, tileData);
                                }
                            });

                            Bounds tileCacheBounds = GeometryHelper.ToBounds(unfinishedTileCache.Bbox);
                            string metadataBounds  = tileCacheBounds.ToCsv();

                            double centerLon      = tileCacheBounds.Center().Lon;
                            double centerLat      = tileCacheBounds.Center().Lat;
                            string metadataCenter = $"{centerLon},{centerLat},{unfinishedTileCache.ZoomLevelMin}";
                            string format         = tileSource.TileServerUrls[0].Url.EndsWith("png") ? "png" : "jpg";

                            tileCacheManager.SaveMetadata(unfinishedTileCache.Name, format, metadataBounds, metadataCenter,
                                                          unfinishedTileCache.ZoomLevelMin ?? 0, unfinishedTileCache.ZoomLevelMax);

                            await TileCacheRepository.SetTileCacheFinished(unfinishedTileCache.TileCacheId,
                                                                           $"{unfinishedTileCache.TileCacheId}.mbtiles");
                        }
                        catch (Exception exception)
                        {
                            Console.WriteLine(exception);
                            Logger.LogWarning(exception,
                                              $"OfflineCacheBackgroundTask: Exception when creating tile cache for campaign {unfinishedTileCache.TileCacheId}.");
                        }
                    }

                    await Task.Delay(5 * 1000, stoppingToken);
                }while (!stoppingToken.IsCancellationRequested);

                Logger.LogInformation("Exiting OfflineCacheBackgroundTask.");
            }
        }