public TileCachesController(IMapper mapper, TileCacheRepository tileCacheRepository, IOptions <ServiceOptions> serviceOptions) { Mapper = mapper; TileCacheRepository = tileCacheRepository; ServiceOptions = serviceOptions.Value; }
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."); } }