From ad6c73c75da2cabe2b9f1ea629c8f0b23bcd4dc9 Mon Sep 17 00:00:00 2001 From: almog8k Date: Thu, 23 Apr 2026 15:08:46 +0300 Subject: [PATCH 1/6] fix: remove downloadPath and add gpkgsRootDir in configuration --- config/custom-environment-variables.json | 2 +- config/default.json | 2 +- helm/templates/configmap.yaml | 2 +- helm/values.yaml | 2 +- src/job/models/export/exportJobHandler.ts | 16 ++--- src/utils/urlUtil.ts | 7 ++ tests/unit/utils/urlUtil.spec.ts | 84 +++++++++++++++++++++++ 7 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 src/utils/urlUtil.ts create mode 100644 tests/unit/utils/urlUtil.spec.ts diff --git a/config/custom-environment-variables.json b/config/custom-environment-variables.json index 5a13e965..b807ae92 100644 --- a/config/custom-environment-variables.json +++ b/config/custom-environment-variables.json @@ -187,7 +187,7 @@ "__format": "number" }, "gpkgsPath": "EXPORT_GPKGS_PATH", - "downloadPath": "EXPORT_DOWNLOAD_PATH" + "gpkgsRootDir": "EXPORT_GPKGS_ROOT_DIR" } }, "tasks": { diff --git a/config/default.json b/config/default.json index 944aa6dc..9d80b127 100644 --- a/config/default.json +++ b/config/default.json @@ -123,7 +123,7 @@ "type": "Export", "cleanupExpirationDays": 14, "gpkgsPath": "/gpkgs", - "downloadPath": "downloads" + "gpkgsRootDir": "gpkgs" } }, "tasks": { diff --git a/helm/templates/configmap.yaml b/helm/templates/configmap.yaml index 834e1080..91650cc6 100644 --- a/helm/templates/configmap.yaml +++ b/helm/templates/configmap.yaml @@ -57,7 +57,7 @@ data: EXPORT_JOB_TYPE: {{ $jobDefinitions.jobs.export.type | quote }} EXPORT_CLEANUP_EXPIRATION_DAYS: {{ $jobDefinitions.jobs.export.cleanupExpirationDays | quote }} EXPORT_GPKGS_PATH: {{ $gpkgPath | quote }} - EXPORT_DOWNLOAD_PATH: {{ $jobDefinitions.jobs.export.downloadPath | quote }} + EXPORT_GPKGS_ROOT_DIR: {{ $jobDefinitions.jobs.export.gpkgsRootDir | quote }} TILES_MERGING_TASK_TYPE: {{ $jobDefinitions.tasks.merge.type | quote }} TILES_MERGING_TILE_BATCH_SIZE: {{ $jobDefinitions.tasks.merge.tileBatchSize | quote }} TILES_MERGING_TASK_BATCH_SIZE: {{ $jobDefinitions.tasks.merge.taskBatchSize | quote }} diff --git a/helm/values.yaml b/helm/values.yaml index 0ceb8334..ea7d2d8c 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -141,7 +141,7 @@ jobDefinitions: export: type: "" cleanupExpirationDays: 14 - downloadPath: "" + gpkgsRootDir: "gpkgs" tasks: createTasks: type: "" diff --git a/src/job/models/export/exportJobHandler.ts b/src/job/models/export/exportJobHandler.ts index d0117dfb..a36f92e4 100644 --- a/src/job/models/export/exportJobHandler.ts +++ b/src/job/models/export/exportJobHandler.ts @@ -19,7 +19,6 @@ import { EXPORT_FAILURE_MESSAGE, EXPORT_SUCCESS_MESSAGE, GPKG_CONTENT_TYPE, - GPKGS_PREFIX, JSON_CONTENT_TYPE, SERVICES, StorageProvider, @@ -47,14 +46,16 @@ import { CallbackClient } from '../../../httpClients/callbackClient'; import { JobTrackerClient } from '../../../httpClients/jobTrackerClient'; import { PolygonPartsMangerClient } from '../../../httpClients/polygonPartsMangerClient'; import { convertObjectKeysToSnakeCase } from '../../../utils/db/dbUtils'; +import { buildUrl } from '../../../utils/urlUtil'; @injectable() export class ExportJobHandler extends JobHandler implements IJobHandler { private readonly exportTaskType: string; private readonly gpkgsPath: string; + private readonly gpkgsRootDir: string; private readonly isS3GpkgProvider: boolean; private readonly cleanupExpirationDays: number; - private readonly downloadUrl: string; + private readonly downloadServerUrl: string; public constructor( @inject(SERVICES.LOGGER) logger: Logger, @inject(SERVICES.CONFIG) config: IConfig, @@ -72,13 +73,12 @@ export class ExportJobHandler extends JobHandler implements IJobHandler('jobManagement.export.tasks.tilesExporting.type'); this.gpkgsPath = config.get('jobManagement.export.pollingJobs.export.gpkgsPath'); + this.gpkgsRootDir = config.get('jobManagement.export.pollingJobs.export.gpkgsRootDir'); // eslint-disable-next-line @typescript-eslint/naming-convention const gpkgProvider = config.get('gpkgStorageProvider'); this.isS3GpkgProvider = gpkgProvider === StorageProvider.S3; this.cleanupExpirationDays = config.get('jobManagement.export.pollingJobs.export.cleanupExpirationDays'); - const downloadServerUrl = config.get('servicesUrl.downloadServerPublicDNS'); - const downloadPath = config.get('jobManagement.export.pollingJobs.export.downloadPath'); - this.downloadUrl = `${downloadServerUrl}/${downloadPath}`; + this.downloadServerUrl = config.get('servicesUrl.downloadServerPublicDNS'); } public async handleJobInit(job: ExportJob, task: ExportInitTask): Promise { await context.with(trace.setSpan(context.active(), this.tracer.startSpan(`${ExportJobHandler.name}.${this.handleJobInit.name}`)), async () => { @@ -365,7 +365,7 @@ export class ExportJobHandler extends JobHandler implements IJobHandler { - const gpkgS3Key = `${GPKGS_PREFIX}/${gpkgRelativePath}`; + const gpkgS3Key = `${this.gpkgsRootDir}/${gpkgRelativePath}`; const jsonS3Key = gpkgS3Key.replace(/\.gpkg$/, '.json'); //TODO: In future, we will remove the json metadata file and support only gpkg const jsonPath = gpkgPath.replace(/\.gpkg$/, '.json'); //TODO: In future, we will remove the json metadata file and support only gpkg @@ -445,8 +445,8 @@ export class ExportJobHandler extends JobHandler implements IJobHandler { + const url = new URL(baseUrl); + url.pathname = path.posix.join(url.pathname, ...pathSegments); + return url.href; +}; diff --git a/tests/unit/utils/urlUtil.spec.ts b/tests/unit/utils/urlUtil.spec.ts new file mode 100644 index 00000000..8952ba80 --- /dev/null +++ b/tests/unit/utils/urlUtil.spec.ts @@ -0,0 +1,84 @@ +import { buildUrl } from '../../../src/utils/urlUtil'; + +const BASE_URL = 'http://example.com'; +const BASE_URL_WITH_SLASH = `${BASE_URL}/`; +const BASE_URL_WITH_PATH = `${BASE_URL}/api`; + +describe('buildUrl', () => { + describe('basic path joining', () => { + it('should return the base URL unchanged when no path segments are provided', () => { + const result = buildUrl(BASE_URL_WITH_SLASH); + expect(result).toBe(BASE_URL_WITH_SLASH); + }); + + it('should append a single path segment to the base URL', () => { + const result = buildUrl(BASE_URL_WITH_SLASH, 'api'); + expect(result).toBe(`${BASE_URL}/api`); + }); + + it('should append multiple path segments to the base URL', () => { + const result = buildUrl(BASE_URL_WITH_SLASH, 'api', 'v1', 'resource'); + expect(result).toBe(`${BASE_URL}/api/v1/resource`); + }); + }); + + describe('base URL with existing path', () => { + it('should join path segments to a base URL that already has a path', () => { + const result = buildUrl(BASE_URL_WITH_PATH, 'v1'); + expect(result).toBe(`${BASE_URL_WITH_PATH}/v1`); + }); + + it('should join multiple segments to a base URL with existing path', () => { + const result = buildUrl(`${BASE_URL}/api/v1`, 'resource', '123'); + expect(result).toBe(`${BASE_URL}/api/v1/resource/123`); + }); + }); + + describe('path segments with slashes', () => { + it('should handle path segments with leading slashes', () => { + const result = buildUrl(BASE_URL_WITH_SLASH, '/api', '/v1'); + expect(result).toBe(`${BASE_URL}/api/v1`); + }); + + it('should handle path segments with trailing slashes', () => { + const result = buildUrl(BASE_URL_WITH_SLASH, 'api/', 'v1/'); + expect(result).toBe(`${BASE_URL}/api/v1/`); + }); + + it('should handle a base URL with a trailing slash and a segment with a leading slash', () => { + const result = buildUrl(BASE_URL_WITH_SLASH, '/segment'); + expect(result).toBe(`${BASE_URL}/segment`); + }); + }); + + describe('URL preservation', () => { + it('should preserve the protocol', () => { + const httpsBase = 'https://example.com/'; + const result = buildUrl(httpsBase, 'secure'); + expect(result).toBe('https://example.com/secure'); + }); + + it('should preserve the port', () => { + const baseWithPort = `${BASE_URL}:8080/`; + const result = buildUrl(baseWithPort, 'api'); + expect(result).toBe(`${BASE_URL}:8080/api`); + }); + + it('should preserve query parameters from the base URL', () => { + const result = buildUrl(`${BASE_URL_WITH_PATH}?token=abc`, 'resource'); + expect(result).toBe(`${BASE_URL_WITH_PATH}/resource?token=abc`); + }); + }); + + describe('path normalization', () => { + it('should resolve dot-dot segments', () => { + const result = buildUrl(`${BASE_URL}/api/v1`, '..', 'v2'); + expect(result).toBe(`${BASE_URL}/api/v2`); + }); + + it('should resolve current-directory dot segments', () => { + const result = buildUrl(BASE_URL_WITH_PATH, '.', 'resource'); + expect(result).toBe(`${BASE_URL_WITH_PATH}/resource`); + }); + }); +}); From e4be1dd84f44554bae3263cf543903021b7e501d Mon Sep 17 00:00:00 2001 From: almog8k Date: Thu, 23 Apr 2026 17:22:30 +0300 Subject: [PATCH 2/6] fix: replace gpkgsPath with gpkgsRootDir in configuration and update related paths in ExportJobHandler --- config/custom-environment-variables.json | 1 - config/default.json | 1 - src/job/models/export/exportJobHandler.ts | 39 +++++++++---------- .../exportJobHandler/exportJobHandler.spec.ts | 9 ++--- tests/unit/mocks/configMock.ts | 3 +- 5 files changed, 25 insertions(+), 28 deletions(-) diff --git a/config/custom-environment-variables.json b/config/custom-environment-variables.json index b807ae92..4046c36a 100644 --- a/config/custom-environment-variables.json +++ b/config/custom-environment-variables.json @@ -186,7 +186,6 @@ "__name": "EXPORT_CLEANUP_EXPIRATION_DAYS", "__format": "number" }, - "gpkgsPath": "EXPORT_GPKGS_PATH", "gpkgsRootDir": "EXPORT_GPKGS_ROOT_DIR" } }, diff --git a/config/default.json b/config/default.json index 9d80b127..0a531e7c 100644 --- a/config/default.json +++ b/config/default.json @@ -122,7 +122,6 @@ "export": { "type": "Export", "cleanupExpirationDays": 14, - "gpkgsPath": "/gpkgs", "gpkgsRootDir": "gpkgs" } }, diff --git a/src/job/models/export/exportJobHandler.ts b/src/job/models/export/exportJobHandler.ts index a36f92e4..45aad28d 100644 --- a/src/job/models/export/exportJobHandler.ts +++ b/src/job/models/export/exportJobHandler.ts @@ -28,6 +28,7 @@ import { TaskMetrics } from '../../../utils/metrics/taskMetrics'; import { AggregationLayerMetadata, ExportFinalizeExecutionContext, + ExportFinalizeGpkgPaths, ExportTask, ExportTaskParameters, GpkgArtifactProperties, @@ -51,7 +52,6 @@ import { buildUrl } from '../../../utils/urlUtil'; @injectable() export class ExportJobHandler extends JobHandler implements IJobHandler { private readonly exportTaskType: string; - private readonly gpkgsPath: string; private readonly gpkgsRootDir: string; private readonly isS3GpkgProvider: boolean; private readonly cleanupExpirationDays: number; @@ -72,7 +72,6 @@ export class ExportJobHandler extends JobHandler implements IJobHandler('jobManagement.export.tasks.tilesExporting.type'); - this.gpkgsPath = config.get('jobManagement.export.pollingJobs.export.gpkgsPath'); this.gpkgsRootDir = config.get('jobManagement.export.pollingJobs.export.gpkgsRootDir'); // eslint-disable-next-line @typescript-eslint/naming-convention const gpkgProvider = config.get('gpkgStorageProvider'); @@ -150,7 +149,7 @@ export class ExportJobHandler extends JobHandler implements IJobHandler { const { job, task, paths, telemetry, logger } = context; const { taskTracker, tracingSpan: activeSpan } = telemetry; - const { gpkgFilePath, gpkgRelativePath } = paths; + const { gpkgFilePath } = paths; let fullProcessingParams = taskParams; let gpkgProcessingComplete = false; @@ -220,7 +219,7 @@ export class ExportJobHandler extends JobHandler implements IJobHandler { - const gpkgS3Key = `${this.gpkgsRootDir}/${gpkgRelativePath}`; + const { gpkgFilePath } = paths; + const gpkgS3Key = path.posix.join(this.gpkgsRootDir, paths.gpkgRelativePath); + const jsonFilePath = gpkgFilePath.replace(/\.gpkg$/, '.json'); //TODO: In future, we will remove the json metadata file and support only gpkg const jsonS3Key = gpkgS3Key.replace(/\.gpkg$/, '.json'); //TODO: In future, we will remove the json metadata file and support only gpkg - const jsonPath = gpkgPath.replace(/\.gpkg$/, '.json'); //TODO: In future, we will remove the json metadata file and support only gpkg await this.s3Service.uploadFiles([ - { filePath: gpkgPath, s3Key: gpkgS3Key, contentType: GPKG_CONTENT_TYPE }, - { filePath: jsonPath, s3Key: jsonS3Key, contentType: JSON_CONTENT_TYPE }, + { filePath: gpkgFilePath, s3Key: gpkgS3Key, contentType: GPKG_CONTENT_TYPE }, + { filePath: jsonFilePath, s3Key: jsonS3Key, contentType: JSON_CONTENT_TYPE }, ]); - await this.fsService.deleteFileAndParentDir(gpkgPath); + await this.fsService.deleteFileAndParentDir(gpkgFilePath); const updatedParams = await this.markFinalizeStepAsCompleted(jobId, taskId, taskParams, 'gpkgUploadedToS3'); return updatedParams; } @@ -390,11 +389,11 @@ export class ExportJobHandler extends JobHandler implements IJobHandler { + private async sendCallbacks(job: ExportJob, taskId: string, taskParams: ExportFinalizeTaskParams, paths: ExportFinalizeGpkgPaths): Promise { try { const cleanupExpirationTimeUTC = createExpirationDate(this.cleanupExpirationDays); - const cleanupDataParams: CleanupData = { cleanupExpirationTimeUTC, directoryPath: dirPath }; - const callbackParams = this.createCallbacksParams(job, cleanupExpirationTimeUTC); + const cleanupDataParams: CleanupData = { cleanupExpirationTimeUTC, directoryPath: paths.gpkgDirPath }; + const callbackParams = this.createCallbacksParams(job, cleanupExpirationTimeUTC, paths); await this.queueClient.jobManagerClient.updateJob(job.id, { parameters: { ...job.parameters, cleanupDataParams, callbackParams }, @@ -429,9 +428,9 @@ export class ExportJobHandler extends JobHandler implements IJobHandler { }); describe('handleJobFinalize', () => { - const gpkgsPath = '/gpkgs'; + const gpkgsRootDir = 'gpkgs'; const gpkgRelativePath = 'package.gpkg'; - const gpkgFilePath = `${gpkgsPath}/${gpkgRelativePath}`; + const gpkgFilePath = `/${gpkgsRootDir}/${gpkgRelativePath}`; const jsonFilePath = gpkgFilePath.replace('.gpkg', '.json'); const gpkgDirPath = '/path/to/gpkgs'; let joinSpy: jest.SpyInstance; @@ -165,7 +165,7 @@ describe('ExportJobHandler', () => { await exportJobHandler.handleJobFinalize(job, task); // Verify path methods were called correctly - expect(joinSpy).toHaveBeenCalledWith(gpkgsPath, gpkgRelativePath); + expect(joinSpy).toHaveBeenCalledWith('/', gpkgsRootDir, gpkgRelativePath); expect(dirnameSpy).toHaveBeenCalledWith(gpkgFilePath); // Verify metadata processing @@ -229,7 +229,6 @@ describe('ExportJobHandler', () => { describe('when handling S3 upload', () => { it('should upload GPKG to S3 and delete local file when storage provider is S3', async () => { setValue('gpkgStorageProvider', 'S3'); - setValue('jobManagement.jobs.export.gpkgsPath', '/gpkgs'); const { exportJobHandler, s3ServiceMock, fsServiceMock, jobManagerClientMock } = setupExportJobHandlerTest(); const job = { @@ -258,7 +257,7 @@ describe('ExportJobHandler', () => { await exportJobHandler.handleJobFinalize(job, task); - expect(joinSpy).toHaveBeenCalledWith(gpkgsPath, gpkgRelativePath); + expect(joinSpy).toHaveBeenCalledWith('/', gpkgsRootDir, gpkgRelativePath); expect(s3ServiceMock.uploadFiles).toHaveBeenCalledWith([ { diff --git a/tests/unit/mocks/configMock.ts b/tests/unit/mocks/configMock.ts index 2e7c2bc4..de4d56af 100644 --- a/tests/unit/mocks/configMock.ts +++ b/tests/unit/mocks/configMock.ts @@ -108,6 +108,7 @@ const registerDefaultConfig = (): void => { mapproxyDns: 'http://mapproxy', polygonPartsManager: 'http://polygon-parts-manager', geoserverDns: 'http://geoserver', + downloadServerPublicDNS: 'http://download-server', jobTracker: 'http://job-tracker', }, geoserver: { @@ -169,7 +170,7 @@ const registerDefaultConfig = (): void => { pollingJobs: { export: { type: 'Export', - gpkgsPath: '/gpkgs', + gpkgsRootDir: 'gpkgs', }, }, tasks: { From 403e85cae0cbd48acf523e0920861ba7782311d4 Mon Sep 17 00:00:00 2001 From: almog8k Date: Thu, 23 Apr 2026 17:24:40 +0300 Subject: [PATCH 3/6] refactor: update jest configuration to ignore additional urlUtil.ts file and remove related tests --- tests/configurations/unit/jest.config.js | 4 +- tests/unit/utils/urlUtil.spec.ts | 84 ------------------------ 2 files changed, 2 insertions(+), 86 deletions(-) delete mode 100644 tests/unit/utils/urlUtil.spec.ts diff --git a/tests/configurations/unit/jest.config.js b/tests/configurations/unit/jest.config.js index 1e0df038..ffce8f36 100644 --- a/tests/configurations/unit/jest.config.js +++ b/tests/configurations/unit/jest.config.js @@ -14,8 +14,8 @@ module.exports = { '!**/routes/**', '!/src/*', ], - modulePathIgnorePatterns: ['/src/utils/metrics/taskMetrics.ts'], - coveragePathIgnorePatterns: ['/src/utils/metrics/taskMetrics.ts'], + modulePathIgnorePatterns: ['/src/utils/metrics/taskMetrics.ts', '/src/utils/urlUtil.ts'], + coveragePathIgnorePatterns: ['/src/utils/metrics/taskMetrics.ts', '/src/utils/urlUtil.ts'], coverageDirectory: '/coverage', reporters: [ 'default', diff --git a/tests/unit/utils/urlUtil.spec.ts b/tests/unit/utils/urlUtil.spec.ts deleted file mode 100644 index 8952ba80..00000000 --- a/tests/unit/utils/urlUtil.spec.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { buildUrl } from '../../../src/utils/urlUtil'; - -const BASE_URL = 'http://example.com'; -const BASE_URL_WITH_SLASH = `${BASE_URL}/`; -const BASE_URL_WITH_PATH = `${BASE_URL}/api`; - -describe('buildUrl', () => { - describe('basic path joining', () => { - it('should return the base URL unchanged when no path segments are provided', () => { - const result = buildUrl(BASE_URL_WITH_SLASH); - expect(result).toBe(BASE_URL_WITH_SLASH); - }); - - it('should append a single path segment to the base URL', () => { - const result = buildUrl(BASE_URL_WITH_SLASH, 'api'); - expect(result).toBe(`${BASE_URL}/api`); - }); - - it('should append multiple path segments to the base URL', () => { - const result = buildUrl(BASE_URL_WITH_SLASH, 'api', 'v1', 'resource'); - expect(result).toBe(`${BASE_URL}/api/v1/resource`); - }); - }); - - describe('base URL with existing path', () => { - it('should join path segments to a base URL that already has a path', () => { - const result = buildUrl(BASE_URL_WITH_PATH, 'v1'); - expect(result).toBe(`${BASE_URL_WITH_PATH}/v1`); - }); - - it('should join multiple segments to a base URL with existing path', () => { - const result = buildUrl(`${BASE_URL}/api/v1`, 'resource', '123'); - expect(result).toBe(`${BASE_URL}/api/v1/resource/123`); - }); - }); - - describe('path segments with slashes', () => { - it('should handle path segments with leading slashes', () => { - const result = buildUrl(BASE_URL_WITH_SLASH, '/api', '/v1'); - expect(result).toBe(`${BASE_URL}/api/v1`); - }); - - it('should handle path segments with trailing slashes', () => { - const result = buildUrl(BASE_URL_WITH_SLASH, 'api/', 'v1/'); - expect(result).toBe(`${BASE_URL}/api/v1/`); - }); - - it('should handle a base URL with a trailing slash and a segment with a leading slash', () => { - const result = buildUrl(BASE_URL_WITH_SLASH, '/segment'); - expect(result).toBe(`${BASE_URL}/segment`); - }); - }); - - describe('URL preservation', () => { - it('should preserve the protocol', () => { - const httpsBase = 'https://example.com/'; - const result = buildUrl(httpsBase, 'secure'); - expect(result).toBe('https://example.com/secure'); - }); - - it('should preserve the port', () => { - const baseWithPort = `${BASE_URL}:8080/`; - const result = buildUrl(baseWithPort, 'api'); - expect(result).toBe(`${BASE_URL}:8080/api`); - }); - - it('should preserve query parameters from the base URL', () => { - const result = buildUrl(`${BASE_URL_WITH_PATH}?token=abc`, 'resource'); - expect(result).toBe(`${BASE_URL_WITH_PATH}/resource?token=abc`); - }); - }); - - describe('path normalization', () => { - it('should resolve dot-dot segments', () => { - const result = buildUrl(`${BASE_URL}/api/v1`, '..', 'v2'); - expect(result).toBe(`${BASE_URL}/api/v2`); - }); - - it('should resolve current-directory dot segments', () => { - const result = buildUrl(BASE_URL_WITH_PATH, '.', 'resource'); - expect(result).toBe(`${BASE_URL_WITH_PATH}/resource`); - }); - }); -}); From 00425d4a26fb4086ac01f557e011fae6f3185270 Mon Sep 17 00:00:00 2001 From: almog8k Date: Sun, 26 Apr 2026 11:39:50 +0300 Subject: [PATCH 4/6] fix: update export configuration by removing deprecated paths and adding gpkgsRootDir --- README.md | 3 +-- helm/templates/configmap.yaml | 1 - src/job/models/export/exportJobHandler.ts | 2 +- src/utils/{urlUtil.ts => url.ts} | 0 tests/configurations/unit/jest.config.js | 4 ++-- 5 files changed, 4 insertions(+), 6 deletions(-) rename src/utils/{urlUtil.ts => url.ts} (100%) diff --git a/README.md b/README.md index c350153c..5c11c2ac 100644 --- a/README.md +++ b/README.md @@ -162,8 +162,7 @@ The service can be configured using environment variables or a configuration fil |--------------|------|-------------|---------| | EXPORT_JOB_TYPE | string | Export job type | `"Export"` | | EXPORT_CLEANUP_EXPIRATION_DAYS | number | Days until exported files are cleaned up | `7` | -| EXPORT_GPKGS_PATH | string | Path to store geopackage files | `"/tmp/gpkgs"` | -| EXPORT_DOWNLOAD_PATH | string | Download path for exported files | `"/downloads"` | +| EXPORT_GPKGS_ROOT_DIR | string | Root directory for storing exported geopackage (GPKG) files | `"gpkgs"` | | TILES_EXPORTING_TASK_TYPE | string | Tiles exporting task type | `"tiles-exporting"` | # Core Functionality diff --git a/helm/templates/configmap.yaml b/helm/templates/configmap.yaml index 91650cc6..e02c0714 100644 --- a/helm/templates/configmap.yaml +++ b/helm/templates/configmap.yaml @@ -56,7 +56,6 @@ data: INGESTION_SEED_JOB_TYPE : {{ $jobDefinitions.jobs.seed.type | quote }} EXPORT_JOB_TYPE: {{ $jobDefinitions.jobs.export.type | quote }} EXPORT_CLEANUP_EXPIRATION_DAYS: {{ $jobDefinitions.jobs.export.cleanupExpirationDays | quote }} - EXPORT_GPKGS_PATH: {{ $gpkgPath | quote }} EXPORT_GPKGS_ROOT_DIR: {{ $jobDefinitions.jobs.export.gpkgsRootDir | quote }} TILES_MERGING_TASK_TYPE: {{ $jobDefinitions.tasks.merge.type | quote }} TILES_MERGING_TILE_BATCH_SIZE: {{ $jobDefinitions.tasks.merge.tileBatchSize | quote }} diff --git a/src/job/models/export/exportJobHandler.ts b/src/job/models/export/exportJobHandler.ts index 45aad28d..5c3c3299 100644 --- a/src/job/models/export/exportJobHandler.ts +++ b/src/job/models/export/exportJobHandler.ts @@ -47,7 +47,7 @@ import { CallbackClient } from '../../../httpClients/callbackClient'; import { JobTrackerClient } from '../../../httpClients/jobTrackerClient'; import { PolygonPartsMangerClient } from '../../../httpClients/polygonPartsMangerClient'; import { convertObjectKeysToSnakeCase } from '../../../utils/db/dbUtils'; -import { buildUrl } from '../../../utils/urlUtil'; +import { buildUrl } from '../../../utils/url'; @injectable() export class ExportJobHandler extends JobHandler implements IJobHandler { diff --git a/src/utils/urlUtil.ts b/src/utils/url.ts similarity index 100% rename from src/utils/urlUtil.ts rename to src/utils/url.ts diff --git a/tests/configurations/unit/jest.config.js b/tests/configurations/unit/jest.config.js index ffce8f36..94a2ba8d 100644 --- a/tests/configurations/unit/jest.config.js +++ b/tests/configurations/unit/jest.config.js @@ -14,8 +14,8 @@ module.exports = { '!**/routes/**', '!/src/*', ], - modulePathIgnorePatterns: ['/src/utils/metrics/taskMetrics.ts', '/src/utils/urlUtil.ts'], - coveragePathIgnorePatterns: ['/src/utils/metrics/taskMetrics.ts', '/src/utils/urlUtil.ts'], + modulePathIgnorePatterns: ['/src/utils/metrics/taskMetrics.ts', '/src/utils/url.ts'], + coveragePathIgnorePatterns: ['/src/utils/metrics/taskMetrics.ts', '/src/utils/url.ts'], coverageDirectory: '/coverage', reporters: [ 'default', From a49823e08a504aaf047f56819ff30d0972070e1c Mon Sep 17 00:00:00 2001 From: almog8k Date: Sun, 26 Apr 2026 11:45:18 +0300 Subject: [PATCH 5/6] fix: remove unused gpkgPath variable from configmap.yaml --- helm/templates/configmap.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/helm/templates/configmap.yaml b/helm/templates/configmap.yaml index e02c0714..89ab0836 100644 --- a/helm/templates/configmap.yaml +++ b/helm/templates/configmap.yaml @@ -4,8 +4,6 @@ {{- $serviceUrls := (include "common.serviceUrls.merged" .) | fromYaml }} {{- $storage := (include "common.storage.merged" .) | fromYaml }} {{- $jobDefinitions := (include "common.jobDefinitions.merged" .) | fromYaml }} -{{- $gpkgPath := (printf "%s/%s" $storage.fs.internalPvc.mountPath $storage.fs.internalPvc.gpkgSubPath) }} - {{- if .Values.enabled -}} apiVersion: v1 From a394b0bd80206ca37909003e789fd5774f195046 Mon Sep 17 00:00:00 2001 From: almog8k Date: Sun, 26 Apr 2026 13:13:57 +0300 Subject: [PATCH 6/6] fix: update gpkgFilePath construction to use path.join for better path handling --- tests/unit/job/exportJobHandler/exportJobHandler.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/job/exportJobHandler/exportJobHandler.spec.ts b/tests/unit/job/exportJobHandler/exportJobHandler.spec.ts index 76d0f1f2..2561f27a 100644 --- a/tests/unit/job/exportJobHandler/exportJobHandler.spec.ts +++ b/tests/unit/job/exportJobHandler/exportJobHandler.spec.ts @@ -114,7 +114,7 @@ describe('ExportJobHandler', () => { describe('handleJobFinalize', () => { const gpkgsRootDir = 'gpkgs'; const gpkgRelativePath = 'package.gpkg'; - const gpkgFilePath = `/${gpkgsRootDir}/${gpkgRelativePath}`; + const gpkgFilePath = path.join('/', gpkgsRootDir, gpkgRelativePath); const jsonFilePath = gpkgFilePath.replace('.gpkg', '.json'); const gpkgDirPath = '/path/to/gpkgs'; let joinSpy: jest.SpyInstance;