Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config/custom-environment-variables.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,9 @@
"seedConcurrency": {
"__name": "SEED_CONCURRENCY",
"__format": "number"
},
"gracefulReloadMaxSeconds": {
"__name": "GRACEFUL_RELOAD_MAX_SECONDS",
"__format": "number"
}
}
3 changes: 2 additions & 1 deletion config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@
"seedProgressFileDir": "/mapproxy/mapproxy_seed_progress"
},
"seedAttempts": 5,
"seedConcurrency": 5
"seedConcurrency": 5,
"gracefulReloadMaxSeconds": 300
}
1 change: 1 addition & 0 deletions helm/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ data:
{{ if $redis.auth.enableRedisUser }}
REDIS_PASSWORD: {{ $redis.auth.password | quote}}
REDIS_USERNAME: {{ $redis.auth.username | quote}}
GRACEFUL_RELOAD_MAX_SECONDS: {{ .Values.global.gracefulReloadMaxSeconds | quote }}
{{ end }}
{{- end }}
1 change: 1 addition & 0 deletions helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ global:
jobManager: ""
heartbeatManager: ""
redis: {}
gracefulReloadMaxSeconds: 300

storage: # local service level
tilesStorageProvider: ""
Expand Down
10 changes: 10 additions & 0 deletions src/cacheSeed/cacheSeedManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { CacheType, SeedMode } from '../common/enums';
export class CacheSeedManager {
private readonly seedAttempts: number;
private readonly taskType: string;
private readonly msToSeconds: number;
private readonly gracefulReloadMaxSeconds: number;

public constructor(
@inject(SERVICES.LOGGER) private readonly logger: Logger,
Expand All @@ -20,6 +22,8 @@ export class CacheSeedManager {
) {
this.seedAttempts = this.config.get<number>('seedAttempts');
this.taskType = this.config.get<string>('queue.tilesTaskType');
this.gracefulReloadMaxSeconds = this.config.get<number>('gracefulReloadMaxSeconds');
this.msToSeconds = 1000;
}

public async handleCacheSeedTask(): Promise<boolean> {
Expand Down Expand Up @@ -61,6 +65,7 @@ export class CacheSeedManager {
return false;
}
try {
await this.delay(this.gracefulReloadMaxSeconds);
await this.runTask(seeds, jobId, taskId);
await this.queueClient.queueHandlerForTileSeedingTasks.ack(jobId, taskId);
await this.queueClient.queueHandlerForTileSeedingTasks.jobManagerClient.updateJob(jobId, {
Expand All @@ -75,6 +80,11 @@ export class CacheSeedManager {
return Boolean(tilesTask);
}

public async delay(seconds: number): Promise<void> {
this.logger.info(`waiting before executing by gracefulReloadRandomSeconds delay for -${seconds}- seconds `);
await new Promise((resolve) => setTimeout(resolve, seconds * this.msToSeconds));
}

private async runTask(seedTasks: ISeed[], jobId: string, taskId: string): Promise<void> {
for (const task of seedTasks) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
Expand Down
1 change: 1 addition & 0 deletions tests/mocks/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ const registerDefaultConfig = (): void => {
geometryTxtFile: '/mapproxy/coverage.json',
seedProgressFileDir: '/mapproxy/mapproxy_seed_progress',
},
gracefulReloadMaxSeconds: 0,
seedAttempts: 5,
};
setConfigValues(config);
Expand Down
23 changes: 18 additions & 5 deletions tests/unit/cacheSeed/cacheSeedManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ describe('CacheSeedManager', () => {
setValue('server.httpRetry', { ...configMock.get<IHttpRetryConfig>('server.httpRetry'), delay: 0 });
mapproxyConfigClient = new MapproxyConfigClient(configMock, jsLogger({ enabled: false }));
queueClient = new QueueClient(configMock, jsLogger({ enabled: false }), configMock.get<IQueueConfig>('queue'));
jest.spyOn(CacheSeedManager.prototype as unknown as { delay: jest.Mock }, 'delay').mockResolvedValue(undefined);

console.warn = jest.fn();
getApp({
Expand Down Expand Up @@ -174,18 +175,16 @@ describe('CacheSeedManager', () => {
it('Reject seed task for getting invalid mode type (not seed or clean on task params', async function () {
const task = { ...getTask(), parameters: { ...getTask().parameters, seedTasks: [{ mode: 'testMode' }] } };
const job = getJob();

dequeueStub = jest.spyOn(queueClient.queueHandlerForTileSeedingTasks, 'dequeue').mockResolvedValue(task);
rejectStubForTileTasks = jest.spyOn(queueClient.queueHandlerForTileSeedingTasks, 'reject').mockImplementation(async () => Promise.resolve());

nock(jobManagerTestUrl).get(`/jobs/${task.jobId}?shouldReturnTasks=false`).reply(200, job); // internal job manager getJob request mocking

const runTaskSpy = jest.spyOn(CacheSeedManager.prototype as unknown as { runTask: jest.Mock }, 'runTask');

getConfigMock.mockResolvedValue({} as unknown as IMapProxyConfig);

// action
await cacheSeedManager.handleCacheSeedTask();
const action = async () => cacheSeedManager.handleCacheSeedTask();

await expect(action()).resolves.not.toThrow();
expect(dequeueStub).toHaveBeenCalledTimes(1);
expect(runTaskSpy).toHaveBeenCalledTimes(1);
expect(rejectStubForTileTasks).toHaveBeenCalledTimes(1);
Expand All @@ -197,4 +196,18 @@ describe('CacheSeedManager', () => {
);
});
});

describe('#Delay', () => {
it('Running timeout', async function () {
jest.spyOn(CacheSeedManager.prototype as unknown as { delay: jest.Mock }, 'delay').mockRestore();
const setTimeoutMock = jest.spyOn(global, 'setTimeout');

// action
const action = async () => cacheSeedManager.delay(0.001);

await expect(action()).resolves.not.toThrow();
expect(setTimeoutMock).toHaveBeenCalledTimes(1);
expect(setTimeoutMock).toHaveBeenCalledWith(expect.anything(), 1);
});
});
});