mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-28 22:19:41 -08:00
fix(core): Use the configured timezone in task runner (#12032)
This commit is contained in:
parent
8616b17cc6
commit
2e6845afcb
|
@ -7,6 +7,7 @@
|
||||||
"args": ["/usr/local/lib/node_modules/n8n/node_modules/@n8n/task-runner/dist/start.js"],
|
"args": ["/usr/local/lib/node_modules/n8n/node_modules/@n8n/task-runner/dist/start.js"],
|
||||||
"allowed-env": [
|
"allowed-env": [
|
||||||
"PATH",
|
"PATH",
|
||||||
|
"GENERIC_TIMEZONE",
|
||||||
"N8N_RUNNERS_GRANT_TOKEN",
|
"N8N_RUNNERS_GRANT_TOKEN",
|
||||||
"N8N_RUNNERS_N8N_URI",
|
"N8N_RUNNERS_N8N_URI",
|
||||||
"N8N_RUNNERS_MAX_PAYLOAD",
|
"N8N_RUNNERS_MAX_PAYLOAD",
|
||||||
|
|
|
@ -34,6 +34,9 @@ export class BaseRunnerConfig {
|
||||||
@Env('N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT')
|
@Env('N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT')
|
||||||
idleTimeout: number = 0;
|
idleTimeout: number = 0;
|
||||||
|
|
||||||
|
@Env('GENERIC_TIMEZONE')
|
||||||
|
timezone: string = 'America/New_York';
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
healthcheckServer!: HealthcheckServerConfig;
|
healthcheckServer!: HealthcheckServerConfig;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import type { CodeExecutionMode, IDataObject } from 'n8n-workflow';
|
import { setGlobalState, type CodeExecutionMode, type IDataObject } from 'n8n-workflow';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import { builtinModules } from 'node:module';
|
import { builtinModules } from 'node:module';
|
||||||
|
|
||||||
|
@ -326,6 +326,43 @@ describe('JsTaskRunner', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('timezone', () => {
|
||||||
|
it('should use the specified timezone in the workflow', async () => {
|
||||||
|
const taskData = newDataRequestResponse(inputItems.map(wrapIntoJson), {});
|
||||||
|
taskData.workflow.settings = {
|
||||||
|
timezone: 'Europe/Helsinki',
|
||||||
|
};
|
||||||
|
|
||||||
|
const outcome = await execTaskWithParams({
|
||||||
|
task: newTaskWithSettings({
|
||||||
|
code: 'return { val: $now.toSeconds() }',
|
||||||
|
nodeMode: 'runOnceForAllItems',
|
||||||
|
}),
|
||||||
|
taskData,
|
||||||
|
});
|
||||||
|
|
||||||
|
const helsinkiTimeNow = DateTime.now().setZone('Europe/Helsinki').toSeconds();
|
||||||
|
expect(outcome.result[0].json.val).toBeCloseTo(helsinkiTimeNow, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use the default timezone', async () => {
|
||||||
|
setGlobalState({
|
||||||
|
defaultTimezone: 'Europe/Helsinki',
|
||||||
|
});
|
||||||
|
|
||||||
|
const outcome = await execTaskWithParams({
|
||||||
|
task: newTaskWithSettings({
|
||||||
|
code: 'return { val: $now.toSeconds() }',
|
||||||
|
nodeMode: 'runOnceForAllItems',
|
||||||
|
}),
|
||||||
|
taskData: newDataRequestResponse(inputItems.map(wrapIntoJson), {}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const helsinkiTimeNow = DateTime.now().setZone('Europe/Helsinki').toSeconds();
|
||||||
|
expect(outcome.result[0].json.val).toBeCloseTo(helsinkiTimeNow, 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should allow access to Node.js Buffers', async () => {
|
it('should allow access to Node.js Buffers', async () => {
|
||||||
const outcomeAll = await execTaskWithParams({
|
const outcomeAll = await execTaskWithParams({
|
||||||
task: newTaskWithSettings({
|
task: newTaskWithSettings({
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ensureError } from 'n8n-workflow';
|
import { ensureError, setGlobalState } from 'n8n-workflow';
|
||||||
import Container from 'typedi';
|
import Container from 'typedi';
|
||||||
|
|
||||||
import { MainConfig } from './config/main-config';
|
import { MainConfig } from './config/main-config';
|
||||||
|
@ -44,6 +44,10 @@ function createSignalHandler(signal: string) {
|
||||||
void (async function start() {
|
void (async function start() {
|
||||||
const config = Container.get(MainConfig);
|
const config = Container.get(MainConfig);
|
||||||
|
|
||||||
|
setGlobalState({
|
||||||
|
defaultTimezone: config.baseRunnerConfig.timezone,
|
||||||
|
});
|
||||||
|
|
||||||
if (config.sentryConfig.sentryDsn) {
|
if (config.sentryConfig.sentryDsn) {
|
||||||
const { ErrorReporter } = await import('@/error-reporter');
|
const { ErrorReporter } = await import('@/error-reporter');
|
||||||
errorReporter = new ErrorReporter(config.sentryConfig);
|
errorReporter = new ErrorReporter(config.sentryConfig);
|
||||||
|
|
|
@ -76,6 +76,7 @@ describe('TaskRunnerProcess', () => {
|
||||||
'N8N_VERSION',
|
'N8N_VERSION',
|
||||||
'ENVIRONMENT',
|
'ENVIRONMENT',
|
||||||
'DEPLOYMENT_NAME',
|
'DEPLOYMENT_NAME',
|
||||||
|
'GENERIC_TIMEZONE',
|
||||||
])('should propagate %s from env as is', async (envVar) => {
|
])('should propagate %s from env as is', async (envVar) => {
|
||||||
jest.spyOn(authService, 'createGrantToken').mockResolvedValue('grantToken');
|
jest.spyOn(authService, 'createGrantToken').mockResolvedValue('grantToken');
|
||||||
process.env[envVar] = 'custom value';
|
process.env[envVar] = 'custom value';
|
||||||
|
|
|
@ -54,6 +54,7 @@ export class TaskRunnerProcess extends TypedEmitter<TaskRunnerProcessEventMap> {
|
||||||
|
|
||||||
private readonly passthroughEnvVars = [
|
private readonly passthroughEnvVars = [
|
||||||
'PATH',
|
'PATH',
|
||||||
|
'GENERIC_TIMEZONE',
|
||||||
'NODE_FUNCTION_ALLOW_BUILTIN',
|
'NODE_FUNCTION_ALLOW_BUILTIN',
|
||||||
'NODE_FUNCTION_ALLOW_EXTERNAL',
|
'NODE_FUNCTION_ALLOW_EXTERNAL',
|
||||||
'N8N_SENTRY_DSN',
|
'N8N_SENTRY_DSN',
|
||||||
|
|
Loading…
Reference in a new issue