refactor(core): Rename push sessionId to pushRef (#8905)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2024-04-03 13:43:14 +02:00 committed by GitHub
parent eaaefd76da
commit 072c3db97d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
58 changed files with 248 additions and 257 deletions

View file

@ -121,7 +121,7 @@ describe('Code node', () => {
.its('request.body') .its('request.body')
.should('have.keys', ['question', 'model', 'context', 'n8nVersion']); .should('have.keys', ['question', 'model', 'context', 'n8nVersion']);
askAiReq.its('context').should('have.keys', ['schema', 'ndvSessionId', 'sessionId']); askAiReq.its('context').should('have.keys', ['schema', 'ndvPushRef', 'pushRef']);
cy.contains('Code generation completed').should('be.visible'); cy.contains('Code generation completed').should('be.visible');
cy.getByTestId('code-node-tab-code').should('contain.text', 'console.log("Hello World")'); cy.getByTestId('code-node-tab-code').should('contain.text', 'console.log("Hello World")');

View file

@ -1,4 +1,3 @@
import type express from 'express';
import { validate } from 'class-validator'; import { validate } from 'class-validator';
import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; import type { CredentialsEntity } from '@db/entities/CredentialsEntity';
@ -7,13 +6,6 @@ import type { User } from '@db/entities/User';
import type { UserRoleChangePayload, UserUpdatePayload } from '@/requests'; import type { UserRoleChangePayload, UserUpdatePayload } from '@/requests';
import { BadRequestError } from './errors/response-errors/bad-request.error'; import { BadRequestError } from './errors/response-errors/bad-request.error';
/**
* Returns the session id if one is set
*/
export function getSessionId(req: express.Request): string | undefined {
return req.headers.sessionid as string | undefined;
}
export async function validateEntity( export async function validateEntity(
entity: entity:
| WorkflowEntity | WorkflowEntity

View file

@ -532,7 +532,7 @@ export interface IWorkflowExecutionDataProcess {
runData?: IRunData; runData?: IRunData;
pinData?: IPinData; pinData?: IPinData;
retryOf?: string; retryOf?: string;
sessionId?: string; pushRef?: string;
startNodes?: StartNodeData[]; startNodes?: StartNodeData[];
workflowData: IWorkflowBase; workflowData: IWorkflowBase;
userId: string; userId: string;

View file

@ -144,8 +144,8 @@ export class InternalHooks {
]); ]);
} }
async onFrontendSettingsAPI(sessionId?: string): Promise<void> { async onFrontendSettingsAPI(pushRef?: string): Promise<void> {
return await this.telemetry.track('Session started', { session_id: sessionId }); return await this.telemetry.track('Session started', { session_id: pushRef });
} }
async onPersonalizationSurveySubmitted( async onPersonalizationSurveySubmitted(

View file

@ -338,7 +338,7 @@ export class Server extends AbstractServer {
`/${this.restEndpoint}/settings`, `/${this.restEndpoint}/settings`,
ResponseHelper.send( ResponseHelper.send(
async (req: express.Request): Promise<IN8nUISettings> => async (req: express.Request): Promise<IN8nUISettings> =>
frontendService.getSettings(req.headers.sessionid as string), frontendService.getSettings(req.headers['push-ref'] as string),
), ),
); );
} }

View file

@ -91,7 +91,7 @@ export class TestWebhooks implements IWebhookManager {
}); });
} }
const { destinationNode, sessionId, workflowEntity, webhook: testWebhook } = registration; const { destinationNode, pushRef, workflowEntity, webhook: testWebhook } = registration;
const workflow = this.toWorkflow(workflowEntity); const workflow = this.toWorkflow(workflowEntity);
@ -112,7 +112,7 @@ export class TestWebhooks implements IWebhookManager {
workflowEntity, workflowEntity,
workflowStartNode, workflowStartNode,
executionMode, executionMode,
sessionId, pushRef,
undefined, // IRunExecutionData undefined, // IRunExecutionData
undefined, // executionId undefined, // executionId
request, request,
@ -130,11 +130,11 @@ export class TestWebhooks implements IWebhookManager {
if (executionId === undefined) return; if (executionId === undefined) return;
// Inform editor-ui that webhook got received // Inform editor-ui that webhook got received
if (sessionId !== undefined) { if (pushRef !== undefined) {
this.push.send( this.push.send(
'testWebhookReceived', 'testWebhookReceived',
{ workflowId: webhook?.workflowId, executionId }, { workflowId: webhook?.workflowId, executionId },
sessionId, pushRef,
); );
} }
} catch {} } catch {}
@ -147,10 +147,10 @@ export class TestWebhooks implements IWebhookManager {
*/ */
if ( if (
this.orchestrationService.isMultiMainSetupEnabled && this.orchestrationService.isMultiMainSetupEnabled &&
sessionId && pushRef &&
!this.push.getBackend().hasSessionId(sessionId) !this.push.getBackend().hasPushRef(pushRef)
) { ) {
const payload = { webhookKey: key, workflowEntity, sessionId }; const payload = { webhookKey: key, workflowEntity, pushRef };
void this.orchestrationService.publish('clear-test-webhooks', payload); void this.orchestrationService.publish('clear-test-webhooks', payload);
return; return;
} }
@ -213,7 +213,7 @@ export class TestWebhooks implements IWebhookManager {
workflowEntity: IWorkflowDb, workflowEntity: IWorkflowDb,
additionalData: IWorkflowExecuteAdditionalData, additionalData: IWorkflowExecuteAdditionalData,
runData?: IRunData, runData?: IRunData,
sessionId?: string, pushRef?: string,
destinationNode?: string, destinationNode?: string,
) { ) {
if (!workflowEntity.id) throw new WorkflowMissingIdError(workflowEntity); if (!workflowEntity.id) throw new WorkflowMissingIdError(workflowEntity);
@ -260,7 +260,7 @@ export class TestWebhooks implements IWebhookManager {
cacheableWebhook.userId = userId; cacheableWebhook.userId = userId;
const registration: TestWebhookRegistration = { const registration: TestWebhookRegistration = {
sessionId, pushRef,
workflowEntity, workflowEntity,
destinationNode, destinationNode,
webhook: cacheableWebhook as IWebhookData, webhook: cacheableWebhook as IWebhookData,
@ -302,7 +302,7 @@ export class TestWebhooks implements IWebhookManager {
if (!registration) continue; if (!registration) continue;
const { sessionId, workflowEntity } = registration; const { pushRef, workflowEntity } = registration;
const workflow = this.toWorkflow(workflowEntity); const workflow = this.toWorkflow(workflowEntity);
@ -310,9 +310,9 @@ export class TestWebhooks implements IWebhookManager {
this.clearTimeout(key); this.clearTimeout(key);
if (sessionId !== undefined) { if (pushRef !== undefined) {
try { try {
this.push.send('testWebhookDeleted', { workflowId }, sessionId); this.push.send('testWebhookDeleted', { workflowId }, pushRef);
} catch { } catch {
// Could not inform editor, probably is not connected anymore. So simply go on. // Could not inform editor, probably is not connected anymore. So simply go on.
} }

View file

@ -223,7 +223,7 @@ export async function executeWebhook(
workflowData: IWorkflowDb, workflowData: IWorkflowDb,
workflowStartNode: INode, workflowStartNode: INode,
executionMode: WorkflowExecuteMode, executionMode: WorkflowExecuteMode,
sessionId: string | undefined, pushRef: string | undefined,
runExecutionData: IRunExecutionData | undefined, runExecutionData: IRunExecutionData | undefined,
executionId: string | undefined, executionId: string | undefined,
req: WebhookRequest, req: WebhookRequest,
@ -541,7 +541,7 @@ export async function executeWebhook(
const runData: IWorkflowExecutionDataProcess = { const runData: IWorkflowExecutionDataProcess = {
executionMode, executionMode,
executionData: runExecutionData, executionData: runExecutionData,
sessionId, pushRef,
workflowData, workflowData,
pinData, pinData,
userId: user.id, userId: user.id,

View file

@ -244,50 +244,50 @@ function hookFunctionsPush(): IWorkflowExecuteHooks {
return { return {
nodeExecuteBefore: [ nodeExecuteBefore: [
async function (this: WorkflowHooks, nodeName: string): Promise<void> { async function (this: WorkflowHooks, nodeName: string): Promise<void> {
const { sessionId, executionId } = this; const { pushRef, executionId } = this;
// Push data to session which started workflow before each // Push data to session which started workflow before each
// node which starts rendering // node which starts rendering
if (sessionId === undefined) { if (pushRef === undefined) {
return; return;
} }
logger.debug(`Executing hook on node "${nodeName}" (hookFunctionsPush)`, { logger.debug(`Executing hook on node "${nodeName}" (hookFunctionsPush)`, {
executionId, executionId,
sessionId, pushRef,
workflowId: this.workflowData.id, workflowId: this.workflowData.id,
}); });
pushInstance.send('nodeExecuteBefore', { executionId, nodeName }, sessionId); pushInstance.send('nodeExecuteBefore', { executionId, nodeName }, pushRef);
}, },
], ],
nodeExecuteAfter: [ nodeExecuteAfter: [
async function (this: WorkflowHooks, nodeName: string, data: ITaskData): Promise<void> { async function (this: WorkflowHooks, nodeName: string, data: ITaskData): Promise<void> {
const { sessionId, executionId } = this; const { pushRef, executionId } = this;
// Push data to session which started workflow after each rendered node // Push data to session which started workflow after each rendered node
if (sessionId === undefined) { if (pushRef === undefined) {
return; return;
} }
logger.debug(`Executing hook on node "${nodeName}" (hookFunctionsPush)`, { logger.debug(`Executing hook on node "${nodeName}" (hookFunctionsPush)`, {
executionId, executionId,
sessionId, pushRef,
workflowId: this.workflowData.id, workflowId: this.workflowData.id,
}); });
pushInstance.send('nodeExecuteAfter', { executionId, nodeName, data }, sessionId); pushInstance.send('nodeExecuteAfter', { executionId, nodeName, data }, pushRef);
}, },
], ],
workflowExecuteBefore: [ workflowExecuteBefore: [
async function (this: WorkflowHooks): Promise<void> { async function (this: WorkflowHooks): Promise<void> {
const { sessionId, executionId } = this; const { pushRef, executionId } = this;
const { id: workflowId, name: workflowName } = this.workflowData; const { id: workflowId, name: workflowName } = this.workflowData;
logger.debug('Executing hook (hookFunctionsPush)', { logger.debug('Executing hook (hookFunctionsPush)', {
executionId, executionId,
sessionId, pushRef,
workflowId, workflowId,
}); });
// Push data to session which started the workflow // Push data to session which started the workflow
if (sessionId === undefined) { if (pushRef === undefined) {
return; return;
} }
pushInstance.send( pushInstance.send(
@ -298,24 +298,24 @@ function hookFunctionsPush(): IWorkflowExecuteHooks {
startedAt: new Date(), startedAt: new Date(),
retryOf: this.retryOf, retryOf: this.retryOf,
workflowId, workflowId,
sessionId, pushRef,
workflowName, workflowName,
}, },
sessionId, pushRef,
); );
}, },
], ],
workflowExecuteAfter: [ workflowExecuteAfter: [
async function (this: WorkflowHooks, fullRunData: IRun): Promise<void> { async function (this: WorkflowHooks, fullRunData: IRun): Promise<void> {
const { sessionId, executionId, retryOf } = this; const { pushRef, executionId, retryOf } = this;
const { id: workflowId } = this.workflowData; const { id: workflowId } = this.workflowData;
logger.debug('Executing hook (hookFunctionsPush)', { logger.debug('Executing hook (hookFunctionsPush)', {
executionId, executionId,
sessionId, pushRef,
workflowId, workflowId,
}); });
// Push data to session which started the workflow // Push data to session which started the workflow
if (sessionId === undefined) { if (pushRef === undefined) {
return; return;
} }
@ -351,7 +351,7 @@ function hookFunctionsPush(): IWorkflowExecuteHooks {
retryOf, retryOf,
}; };
pushInstance.send('executionFinished', sendData, sessionId); pushInstance.send('executionFinished', sendData, pushRef);
}, },
], ],
}; };
@ -378,7 +378,7 @@ export function hookFunctionsPreExecute(): IWorkflowExecuteHooks {
nodeName, nodeName,
data, data,
executionData, executionData,
this.sessionId, this.pushRef,
); );
}, },
], ],
@ -578,7 +578,7 @@ function hookFunctionsSaveWorker(): IWorkflowExecuteHooks {
ErrorReporter.error(e); ErrorReporter.error(e);
logger.error( logger.error(
`There was a problem saving the workflow with id "${this.workflowData.id}" to save changed staticData: "${e.message}" (workflowExecuteAfter)`, `There was a problem saving the workflow with id "${this.workflowData.id}" to save changed staticData: "${e.message}" (workflowExecuteAfter)`,
{ sessionId: this.sessionId, workflowId: this.workflowData.id }, { pushRef: this.pushRef, workflowId: this.workflowData.id },
); );
} }
} }
@ -939,15 +939,15 @@ export function setExecutionStatus(status: ExecutionStatus) {
} }
export function sendDataToUI(type: string, data: IDataObject | IDataObject[]) { export function sendDataToUI(type: string, data: IDataObject | IDataObject[]) {
const { sessionId } = this; const { pushRef } = this;
if (sessionId === undefined) { if (pushRef === undefined) {
return; return;
} }
// Push data to session which started workflow // Push data to session which started workflow
try { try {
const pushInstance = Container.get(Push); const pushInstance = Container.get(Push);
pushInstance.send(type as IPushDataType, data, sessionId); pushInstance.send(type as IPushDataType, data, pushRef);
} catch (error) { } catch (error) {
const logger = Container.get(Logger); const logger = Container.get(Logger);
logger.warn(`There was a problem sending message to UI: ${error.message}`); logger.warn(`There was a problem sending message to UI: ${error.message}`);
@ -1128,7 +1128,7 @@ export function getWorkflowHooksMain(
if (!hookFunctions.nodeExecuteAfter) hookFunctions.nodeExecuteAfter = []; if (!hookFunctions.nodeExecuteAfter) hookFunctions.nodeExecuteAfter = [];
return new WorkflowHooks(hookFunctions, data.executionMode, executionId, data.workflowData, { return new WorkflowHooks(hookFunctions, data.executionMode, executionId, data.workflowData, {
sessionId: data.sessionId, pushRef: data.pushRef,
retryOf: data.retryOf as string, retryOf: data.retryOf as string,
}); });
} }

View file

@ -295,7 +295,7 @@ export class WorkflowRunner {
}); });
additionalData.sendDataToUI = WorkflowExecuteAdditionalData.sendDataToUI.bind({ additionalData.sendDataToUI = WorkflowExecuteAdditionalData.sendDataToUI.bind({
sessionId: data.sessionId, pushRef: data.pushRef,
}); });
await additionalData.hooks.executeHookFunctions('workflowExecuteBefore', []); await additionalData.hooks.executeHookFunctions('workflowExecuteBefore', []);

View file

@ -55,7 +55,7 @@ type PushRequest = Request<
{}, {},
{ {
type: IPushDataType; type: IPushDataType;
sessionId: string; pushRef: string;
data: object; data: object;
} }
>; >;

View file

@ -13,7 +13,7 @@ export async function saveExecutionProgress(
nodeName: string, nodeName: string,
data: ITaskData, data: ITaskData,
executionData: IRunExecutionData, executionData: IRunExecutionData,
sessionId?: string, pushRef?: string,
) { ) {
const saveSettings = toSaveSettings(workflowData.settings); const saveSettings = toSaveSettings(workflowData.settings);
@ -97,7 +97,7 @@ export async function saveExecutionProgress(
{ {
...error, ...error,
executionId, executionId,
sessionId, pushRef,
workflowId: workflowData.id, workflowId: workflowData.id,
}, },
); );

View file

@ -8,7 +8,7 @@ export const corsMiddleware: RequestHandler = (req, res, next) => {
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.header( res.header(
'Access-Control-Allow-Headers', 'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, sessionid', 'Origin, X-Requested-With, Content-Type, Accept, push-ref',
); );
} }

View file

@ -14,7 +14,7 @@ import type { OrchestrationService } from '@/services/orchestration.service';
export abstract class AbstractPush<T> extends EventEmitter { export abstract class AbstractPush<T> extends EventEmitter {
protected connections: Record<string, T> = {}; protected connections: Record<string, T> = {};
protected userIdBySessionId: Record<string, string> = {}; protected userIdByPushRef: Record<string, string> = {};
protected abstract close(connection: T): void; protected abstract close(connection: T): void;
protected abstract sendToOneConnection(connection: T, data: string): void; protected abstract sendToOneConnection(connection: T, data: string): void;
@ -26,100 +26,100 @@ export abstract class AbstractPush<T> extends EventEmitter {
super(); super();
} }
protected add(sessionId: string, userId: User['id'], connection: T) { protected add(pushRef: string, userId: User['id'], connection: T) {
const { connections, userIdBySessionId: userIdsBySessionId } = this; const { connections, userIdByPushRef } = this;
this.logger.debug('Add editor-UI session', { sessionId }); this.logger.debug('Add editor-UI session', { pushRef });
const existingConnection = connections[sessionId]; const existingConnection = connections[pushRef];
if (existingConnection) { if (existingConnection) {
// Make sure to remove existing connection with the same ID // Make sure to remove existing connection with the same ID
this.close(existingConnection); this.close(existingConnection);
} }
connections[sessionId] = connection; connections[pushRef] = connection;
userIdsBySessionId[sessionId] = userId; userIdByPushRef[pushRef] = userId;
} }
protected onMessageReceived(sessionId: string, msg: unknown) { protected onMessageReceived(pushRef: string, msg: unknown) {
this.logger.debug('Received message from editor-UI', { sessionId, msg }); this.logger.debug('Received message from editor-UI', { pushRef, msg });
const userId = this.userIdBySessionId[sessionId]; const userId = this.userIdByPushRef[pushRef];
this.emit('message', { sessionId, userId, msg }); this.emit('message', { pushRef, userId, msg });
} }
protected remove(sessionId?: string) { protected remove(pushRef?: string) {
if (!sessionId) return; if (!pushRef) return;
this.logger.debug('Removed editor-UI session', { sessionId }); this.logger.debug('Removed editor-UI session', { pushRef });
delete this.connections[sessionId]; delete this.connections[pushRef];
delete this.userIdBySessionId[sessionId]; delete this.userIdByPushRef[pushRef];
} }
private sendToSessions(type: IPushDataType, data: unknown, sessionIds: string[]) { private sendTo(type: IPushDataType, data: unknown, pushRefs: string[]) {
this.logger.debug(`Send data of type "${type}" to editor-UI`, { this.logger.debug(`Send data of type "${type}" to editor-UI`, {
dataType: type, dataType: type,
sessionIds: sessionIds.join(', '), pushRefs: pushRefs.join(', '),
}); });
const stringifiedPayload = jsonStringify({ type, data }, { replaceCircularRefs: true }); const stringifiedPayload = jsonStringify({ type, data }, { replaceCircularRefs: true });
for (const sessionId of sessionIds) { for (const pushRef of pushRefs) {
const connection = this.connections[sessionId]; const connection = this.connections[pushRef];
assert(connection); assert(connection);
this.sendToOneConnection(connection, stringifiedPayload); this.sendToOneConnection(connection, stringifiedPayload);
} }
} }
sendToAllSessions(type: IPushDataType, data?: unknown) { sendToAll(type: IPushDataType, data?: unknown) {
this.sendToSessions(type, data, Object.keys(this.connections)); this.sendTo(type, data, Object.keys(this.connections));
} }
sendToOneSession(type: IPushDataType, data: unknown, sessionId: string) { sendToOneSession(type: IPushDataType, data: unknown, pushRef: string) {
/** /**
* Multi-main setup: In a manual webhook execution, the main process that * Multi-main setup: In a manual webhook execution, the main process that
* handles a webhook might not be the same as the main process that created * handles a webhook might not be the same as the main process that created
* the webhook. If so, the handler process commands the creator process to * the webhook. If so, the handler process commands the creator process to
* relay the former's execution lifecyle events to the creator's frontend. * relay the former's execution lifecycle events to the creator's frontend.
*/ */
if (this.orchestrationService.isMultiMainSetupEnabled && !this.hasSessionId(sessionId)) { if (this.orchestrationService.isMultiMainSetupEnabled && !this.hasPushRef(pushRef)) {
const payload = { type, args: data, sessionId }; const payload = { type, args: data, pushRef };
void this.orchestrationService.publish('relay-execution-lifecycle-event', payload); void this.orchestrationService.publish('relay-execution-lifecycle-event', payload);
return; return;
} }
if (this.connections[sessionId] === undefined) { if (this.connections[pushRef] === undefined) {
this.logger.error(`The session "${sessionId}" is not registered.`, { sessionId }); this.logger.error(`The session "${pushRef}" is not registered.`, { pushRef });
return; return;
} }
this.sendToSessions(type, data, [sessionId]); this.sendTo(type, data, [pushRef]);
} }
sendToUsers(type: IPushDataType, data: unknown, userIds: Array<User['id']>) { sendToUsers(type: IPushDataType, data: unknown, userIds: Array<User['id']>) {
const { connections } = this; const { connections } = this;
const userSessionIds = Object.keys(connections).filter((sessionId) => const userPushRefs = Object.keys(connections).filter((pushRef) =>
userIds.includes(this.userIdBySessionId[sessionId]), userIds.includes(this.userIdByPushRef[pushRef]),
); );
this.sendToSessions(type, data, userSessionIds); this.sendTo(type, data, userPushRefs);
} }
closeAllConnections() { closeAllConnections() {
for (const sessionId in this.connections) { for (const pushRef in this.connections) {
// Signal the connection that we want to close it. // Signal the connection that we want to close it.
// We are not removing the sessions here because it should be // We are not removing the sessions here because it should be
// the implementation's responsibility to do so once the connection // the implementation's responsibility to do so once the connection
// has actually closed. // has actually closed.
this.close(this.connections[sessionId]); this.close(this.connections[pushRef]);
} }
} }
hasSessionId(sessionId: string) { hasPushRef(pushRef: string) {
return this.connections[sessionId] !== undefined; return this.connections[pushRef] !== undefined;
} }
} }

View file

@ -41,36 +41,36 @@ export class Push extends EventEmitter {
const { const {
user, user,
ws, ws,
query: { sessionId }, query: { pushRef },
} = req; } = req;
if (!sessionId) { if (!pushRef) {
if (ws) { if (ws) {
ws.send('The query parameter "sessionId" is missing!'); ws.send('The query parameter "pushRef" is missing!');
ws.close(1008); ws.close(1008);
return; return;
} }
throw new BadRequestError('The query parameter "sessionId" is missing!'); throw new BadRequestError('The query parameter "pushRef" is missing!');
} }
if (req.ws) { if (req.ws) {
(this.backend as WebSocketPush).add(sessionId, user.id, req.ws); (this.backend as WebSocketPush).add(pushRef, user.id, req.ws);
} else if (!useWebSockets) { } else if (!useWebSockets) {
(this.backend as SSEPush).add(sessionId, user.id, { req, res }); (this.backend as SSEPush).add(pushRef, user.id, { req, res });
} else { } else {
res.status(401).send('Unauthorized'); res.status(401).send('Unauthorized');
return; return;
} }
this.emit('editorUiConnected', sessionId); this.emit('editorUiConnected', pushRef);
} }
broadcast(type: IPushDataType, data?: unknown) { broadcast(type: IPushDataType, data?: unknown) {
this.backend.sendToAllSessions(type, data); this.backend.sendToAll(type, data);
} }
send(type: IPushDataType, data: unknown, sessionId: string) { send(type: IPushDataType, data: unknown, pushRef: string) {
this.backend.sendToOneSession(type, data, sessionId); this.backend.sendToOneSession(type, data, pushRef);
} }
getBackend() { getBackend() {

View file

@ -17,13 +17,13 @@ export class SSEPush extends AbstractPush<Connection> {
constructor(logger: Logger, orchestrationService: OrchestrationService) { constructor(logger: Logger, orchestrationService: OrchestrationService) {
super(logger, orchestrationService); super(logger, orchestrationService);
this.channel.on('disconnect', (channel, { req }) => { this.channel.on('disconnect', (_, { req }) => {
this.remove(req?.query?.sessionId); this.remove(req?.query?.pushRef);
}); });
} }
add(sessionId: string, userId: User['id'], connection: Connection) { add(pushRef: string, userId: User['id'], connection: Connection) {
super.add(sessionId, userId, connection); super.add(pushRef, userId, connection);
this.channel.addClient(connection.req, connection.res); this.channel.addClient(connection.req, connection.res);
} }

View file

@ -6,7 +6,7 @@ import type { AuthenticatedRequest } from '@/requests';
// TODO: move all push related types here // TODO: move all push related types here
export type PushRequest = AuthenticatedRequest<{}, {}, {}, { sessionId: string }>; export type PushRequest = AuthenticatedRequest<{}, {}, {}, { pushRef: string }>;
export type SSEPushRequest = PushRequest & { ws: undefined }; export type SSEPushRequest = PushRequest & { ws: undefined };
export type WebSocketPushRequest = PushRequest & { ws: WebSocket }; export type WebSocketPushRequest = PushRequest & { ws: WebSocket };
@ -14,7 +14,7 @@ export type WebSocketPushRequest = PushRequest & { ws: WebSocket };
export type PushResponse = Response & { req: PushRequest }; export type PushResponse = Response & { req: PushRequest };
export type OnPushMessageEvent = { export type OnPushMessageEvent = {
sessionId: string; pushRef: string;
userId: User['id']; userId: User['id'];
msg: unknown; msg: unknown;
}; };

View file

@ -18,21 +18,21 @@ export class WebSocketPush extends AbstractPush<WebSocket> {
setInterval(() => this.pingAll(), 60 * 1000); setInterval(() => this.pingAll(), 60 * 1000);
} }
add(sessionId: string, userId: User['id'], connection: WebSocket) { add(pushRef: string, userId: User['id'], connection: WebSocket) {
connection.isAlive = true; connection.isAlive = true;
connection.on('pong', heartbeat); connection.on('pong', heartbeat);
super.add(sessionId, userId, connection); super.add(pushRef, userId, connection);
const onMessage = (data: WebSocket.RawData) => { const onMessage = (data: WebSocket.RawData) => {
try { try {
const buffer = Array.isArray(data) ? Buffer.concat(data) : Buffer.from(data); const buffer = Array.isArray(data) ? Buffer.concat(data) : Buffer.from(data);
this.onMessageReceived(sessionId, JSON.parse(buffer.toString('utf8'))); this.onMessageReceived(pushRef, JSON.parse(buffer.toString('utf8')));
} catch (error) { } catch (error) {
this.logger.error("Couldn't parse message from editor-UI", { this.logger.error("Couldn't parse message from editor-UI", {
error: error as unknown, error: error as unknown,
sessionId, pushRef,
data, data,
}); });
} }
@ -42,7 +42,7 @@ export class WebSocketPush extends AbstractPush<WebSocket> {
connection.once('close', () => { connection.once('close', () => {
connection.off('pong', heartbeat); connection.off('pong', heartbeat);
connection.off('message', onMessage); connection.off('message', onMessage);
this.remove(sessionId); this.remove(pushRef);
}); });
connection.on('message', onMessage); connection.on('message', onMessage);
@ -57,11 +57,11 @@ export class WebSocketPush extends AbstractPush<WebSocket> {
} }
private pingAll() { private pingAll() {
for (const sessionId in this.connections) { for (const pushRef in this.connections) {
const connection = this.connections[sessionId]; const connection = this.connections[pushRef];
// If a connection did not respond with a `PONG` in the last 60 seconds, disconnect // If a connection did not respond with a `PONG` in the last 60 seconds, disconnect
if (!connection.isAlive) { if (!connection.isAlive) {
delete this.connections[sessionId]; delete this.connections[pushRef];
return connection.terminate(); return connection.terminate();
} }

View file

@ -225,8 +225,8 @@ export class FrontendService {
this.writeStaticJSON('credentials', credentials); this.writeStaticJSON('credentials', credentials);
} }
getSettings(sessionId?: string): IN8nUISettings { getSettings(pushRef?: string): IN8nUISettings {
void this.internalHooks.onFrontendSettingsAPI(sessionId); void this.internalHooks.onFrontendSettingsAPI(pushRef);
const restEndpoint = config.getEnv('endpoints.rest'); const restEndpoint = config.getEnv('endpoints.rest');

View file

@ -196,11 +196,11 @@ export async function handleCommandMessageMain(messageString: string) {
* Do not debounce this - all events share the same message name. * Do not debounce this - all events share the same message name.
*/ */
const { type, args, sessionId } = message.payload; const { type, args, pushRef } = message.payload;
if (!push.getBackend().hasSessionId(sessionId)) break; if (!push.getBackend().hasPushRef(pushRef)) break;
push.send(type, args, sessionId); push.send(type, args, pushRef);
break; break;
} }
@ -212,9 +212,9 @@ export async function handleCommandMessageMain(messageString: string) {
return message; return message;
} }
const { webhookKey, workflowEntity, sessionId } = message.payload; const { webhookKey, workflowEntity, pushRef } = message.payload;
if (!push.getBackend().hasSessionId(sessionId)) break; if (!push.getBackend().hasPushRef(pushRef)) break;
const testWebhooks = Container.get(TestWebhooks); const testWebhooks = Container.get(TestWebhooks);

View file

@ -35,12 +35,12 @@ export type RedisServiceBaseCommand =
| { | {
senderId: string; senderId: string;
command: 'relay-execution-lifecycle-event'; command: 'relay-execution-lifecycle-event';
payload: { type: IPushDataType; args: Record<string, unknown>; sessionId: string }; payload: { type: IPushDataType; args: Record<string, unknown>; pushRef: string };
} }
| { | {
senderId: string; senderId: string;
command: 'clear-test-webhooks'; command: 'clear-test-webhooks';
payload: { webhookKey: string; workflowEntity: IWorkflowDb; sessionId: string }; payload: { webhookKey: string; workflowEntity: IWorkflowDb; pushRef: string };
}; };
export type RedisServiceWorkerResponseObject = { export type RedisServiceWorkerResponseObject = {

View file

@ -5,7 +5,7 @@ import type { IWorkflowDb } from '@/Interfaces';
import { TEST_WEBHOOK_TIMEOUT, TEST_WEBHOOK_TIMEOUT_BUFFER } from '@/constants'; import { TEST_WEBHOOK_TIMEOUT, TEST_WEBHOOK_TIMEOUT_BUFFER } from '@/constants';
export type TestWebhookRegistration = { export type TestWebhookRegistration = {
sessionId?: string; pushRef?: string;
workflowEntity: IWorkflowDb; workflowEntity: IWorkflowDb;
destinationNode?: string; destinationNode?: string;
webhook: IWebhookData; webhook: IWebhookData;

View file

@ -99,7 +99,7 @@ export class WorkflowExecutionService {
destinationNode, destinationNode,
}: WorkflowRequest.ManualRunPayload, }: WorkflowRequest.ManualRunPayload,
user: User, user: User,
sessionId?: string, pushRef?: string,
) { ) {
const pinnedTrigger = this.selectPinnedActivatorStarter( const pinnedTrigger = this.selectPinnedActivatorStarter(
workflowData, workflowData,
@ -122,7 +122,7 @@ export class WorkflowExecutionService {
workflowData, workflowData,
additionalData, additionalData,
runData, runData,
sessionId, pushRef,
destinationNode, destinationNode,
); );
@ -138,7 +138,7 @@ export class WorkflowExecutionService {
executionMode: 'manual', executionMode: 'manual',
runData, runData,
pinData, pinData,
sessionId, pushRef,
startNodes, startNodes,
workflowData, workflowData,
userId: user.id, userId: user.id,

View file

@ -3,7 +3,6 @@ import { v4 as uuid } from 'uuid';
import axios from 'axios'; import axios from 'axios';
import * as Db from '@/Db'; import * as Db from '@/Db';
import * as GenericHelpers from '@/GenericHelpers';
import * as ResponseHelper from '@/ResponseHelper'; import * as ResponseHelper from '@/ResponseHelper';
import * as WorkflowHelpers from '@/WorkflowHelpers'; import * as WorkflowHelpers from '@/WorkflowHelpers';
import type { IWorkflowResponse } from '@/Interfaces'; import type { IWorkflowResponse } from '@/Interfaces';
@ -331,7 +330,7 @@ export class WorkflowsController {
return await this.workflowExecutionService.executeManually( return await this.workflowExecutionService.executeManually(
req.body, req.body,
req.user, req.user,
GenericHelpers.getSessionId(req), req.headers['push-ref'] as string,
); );
} }

View file

@ -105,7 +105,7 @@ describe('TestWebhooks', () => {
jest.spyOn(testWebhooks, 'getWebhookMethods').mockResolvedValue([]); jest.spyOn(testWebhooks, 'getWebhookMethods').mockResolvedValue([]);
const registration = mock<TestWebhookRegistration>({ const registration = mock<TestWebhookRegistration>({
sessionId: 'some-session-id', pushRef: 'some-session-id',
workflowEntity, workflowEntity,
}); });

View file

@ -17,12 +17,12 @@ describe('Push', () => {
const sseBackend = mockInstance(SSEPush); const sseBackend = mockInstance(SSEPush);
const wsBackend = mockInstance(WebSocketPush); const wsBackend = mockInstance(WebSocketPush);
test('should validate sessionId on requests for websocket backend', () => { test('should validate pushRef on requests for websocket backend', () => {
config.set('push.backend', 'websocket'); config.set('push.backend', 'websocket');
const push = new Push(); const push = new Push();
const ws = mock<WebSocket>(); const ws = mock<WebSocket>();
const request = mock<WebSocketPushRequest>({ user, ws }); const request = mock<WebSocketPushRequest>({ user, ws });
request.query = { sessionId: '' }; request.query = { pushRef: '' };
push.handleRequest(request, mock()); push.handleRequest(request, mock());
expect(ws.send).toHaveBeenCalled(); expect(ws.send).toHaveBeenCalled();
@ -30,11 +30,11 @@ describe('Push', () => {
expect(wsBackend.add).not.toHaveBeenCalled(); expect(wsBackend.add).not.toHaveBeenCalled();
}); });
test('should validate sessionId on requests for SSE backend', () => { test('should validate pushRef on requests for SSE backend', () => {
config.set('push.backend', 'sse'); config.set('push.backend', 'sse');
const push = new Push(); const push = new Push();
const request = mock<SSEPushRequest>({ user, ws: undefined }); const request = mock<SSEPushRequest>({ user, ws: undefined });
request.query = { sessionId: '' }; request.query = { pushRef: '' };
expect(() => push.handleRequest(request, mock())).toThrow(BadRequestError); expect(() => push.handleRequest(request, mock())).toThrow(BadRequestError);
expect(sseBackend.add).not.toHaveBeenCalled(); expect(sseBackend.add).not.toHaveBeenCalled();

View file

@ -24,8 +24,8 @@ class MockWebSocket extends EventEmitter {
const createMockWebSocket = () => new MockWebSocket() as unknown as jest.Mocked<WebSocket>; const createMockWebSocket = () => new MockWebSocket() as unknown as jest.Mocked<WebSocket>;
describe('WebSocketPush', () => { describe('WebSocketPush', () => {
const sessionId1 = 'test-session1'; const pushRef1 = 'test-session1';
const sessionId2 = 'test-session2'; const pushRef2 = 'test-session2';
const userId: User['id'] = 'test-user'; const userId: User['id'] = 'test-user';
mockInstance(Logger); mockInstance(Logger);
@ -38,7 +38,7 @@ describe('WebSocketPush', () => {
}); });
it('can add a connection', () => { it('can add a connection', () => {
webSocketPush.add(sessionId1, userId, mockWebSocket1); webSocketPush.add(pushRef1, userId, mockWebSocket1);
expect(mockWebSocket1.listenerCount('close')).toBe(1); expect(mockWebSocket1.listenerCount('close')).toBe(1);
expect(mockWebSocket1.listenerCount('pong')).toBe(1); expect(mockWebSocket1.listenerCount('pong')).toBe(1);
@ -46,7 +46,7 @@ describe('WebSocketPush', () => {
}); });
it('closes a connection', () => { it('closes a connection', () => {
webSocketPush.add(sessionId1, userId, mockWebSocket1); webSocketPush.add(pushRef1, userId, mockWebSocket1);
mockWebSocket1.emit('close'); mockWebSocket1.emit('close');
@ -56,8 +56,8 @@ describe('WebSocketPush', () => {
}); });
it('sends data to one connection', () => { it('sends data to one connection', () => {
webSocketPush.add(sessionId1, userId, mockWebSocket1); webSocketPush.add(pushRef1, userId, mockWebSocket1);
webSocketPush.add(sessionId2, userId, mockWebSocket2); webSocketPush.add(pushRef2, userId, mockWebSocket2);
const data: PushDataExecutionRecovered = { const data: PushDataExecutionRecovered = {
type: 'executionRecovered', type: 'executionRecovered',
data: { data: {
@ -65,7 +65,7 @@ describe('WebSocketPush', () => {
}, },
}; };
webSocketPush.sendToOneSession('executionRecovered', data, sessionId1); webSocketPush.sendToOneSession('executionRecovered', data, pushRef1);
expect(mockWebSocket1.send).toHaveBeenCalledWith( expect(mockWebSocket1.send).toHaveBeenCalledWith(
JSON.stringify({ JSON.stringify({
@ -82,8 +82,8 @@ describe('WebSocketPush', () => {
}); });
it('sends data to all connections', () => { it('sends data to all connections', () => {
webSocketPush.add(sessionId1, userId, mockWebSocket1); webSocketPush.add(pushRef1, userId, mockWebSocket1);
webSocketPush.add(sessionId2, userId, mockWebSocket2); webSocketPush.add(pushRef2, userId, mockWebSocket2);
const data: PushDataExecutionRecovered = { const data: PushDataExecutionRecovered = {
type: 'executionRecovered', type: 'executionRecovered',
data: { data: {
@ -91,7 +91,7 @@ describe('WebSocketPush', () => {
}, },
}; };
webSocketPush.sendToAllSessions('executionRecovered', data); webSocketPush.sendToAll('executionRecovered', data);
const expectedMsg = JSON.stringify({ const expectedMsg = JSON.stringify({
type: 'executionRecovered', type: 'executionRecovered',
@ -107,8 +107,8 @@ describe('WebSocketPush', () => {
}); });
it('sends data to all users connections', () => { it('sends data to all users connections', () => {
webSocketPush.add(sessionId1, userId, mockWebSocket1); webSocketPush.add(pushRef1, userId, mockWebSocket1);
webSocketPush.add(sessionId2, userId, mockWebSocket2); webSocketPush.add(pushRef2, userId, mockWebSocket2);
const data: PushDataExecutionRecovered = { const data: PushDataExecutionRecovered = {
type: 'executionRecovered', type: 'executionRecovered',
data: { data: {
@ -132,8 +132,8 @@ describe('WebSocketPush', () => {
}); });
it('pings all connections', () => { it('pings all connections', () => {
webSocketPush.add(sessionId1, userId, mockWebSocket1); webSocketPush.add(pushRef1, userId, mockWebSocket1);
webSocketPush.add(sessionId2, userId, mockWebSocket2); webSocketPush.add(pushRef2, userId, mockWebSocket2);
jest.runOnlyPendingTimers(); jest.runOnlyPendingTimers();
@ -144,8 +144,8 @@ describe('WebSocketPush', () => {
it('emits message event when connection receives data', () => { it('emits message event when connection receives data', () => {
const mockOnMessageReceived = jest.fn(); const mockOnMessageReceived = jest.fn();
webSocketPush.on('message', mockOnMessageReceived); webSocketPush.on('message', mockOnMessageReceived);
webSocketPush.add(sessionId1, userId, mockWebSocket1); webSocketPush.add(pushRef1, userId, mockWebSocket1);
webSocketPush.add(sessionId2, userId, mockWebSocket2); webSocketPush.add(pushRef2, userId, mockWebSocket2);
const data = { test: 'data' }; const data = { test: 'data' };
const buffer = Buffer.from(JSON.stringify(data)); const buffer = Buffer.from(JSON.stringify(data));
@ -154,7 +154,7 @@ describe('WebSocketPush', () => {
expect(mockOnMessageReceived).toHaveBeenCalledWith({ expect(mockOnMessageReceived).toHaveBeenCalledWith({
msg: data, msg: data,
sessionId: sessionId1, pushRef: pushRef1,
userId, userId,
}); });
}); });

View file

@ -1102,7 +1102,7 @@ export interface RootState {
n8nMetadata: { n8nMetadata: {
[key: string]: string | number | undefined; [key: string]: string | number | undefined;
}; };
sessionId: string; pushRef: string;
urlBaseWebhook: string; urlBaseWebhook: string;
urlBaseEditor: string; urlBaseEditor: string;
instanceId: string; instanceId: string;
@ -1146,7 +1146,7 @@ export interface IRootState {
nodeViewOffsetPosition: XYPosition; nodeViewOffsetPosition: XYPosition;
nodeViewMoveInProgress: boolean; nodeViewMoveInProgress: boolean;
selectedNodes: INodeUi[]; selectedNodes: INodeUi[];
sessionId: string; pushRef: string;
urlBaseEditor: string; urlBaseEditor: string;
urlBaseWebhook: string; urlBaseWebhook: string;
workflow: IWorkflowDb; workflow: IWorkflowDb;
@ -1214,7 +1214,7 @@ export interface TargetItem {
export interface NDVState { export interface NDVState {
activeNodeName: string | null; activeNodeName: string | null;
mainPanelDimensions: { [key: string]: { [key: string]: number } }; mainPanelDimensions: { [key: string]: { [key: string]: number } };
sessionId: string; pushRef: string;
input: { input: {
displayMode: IRunDataDisplayMode; displayMode: IRunDataDisplayMode;
nodeName?: string; nodeName?: string;
@ -1428,7 +1428,7 @@ export interface CommunityNodesState {
export interface IRestApiContext { export interface IRestApiContext {
baseUrl: string; baseUrl: string;
sessionId: string; pushRef: string;
} }
export interface IZoomConfig { export interface IZoomConfig {

View file

@ -18,8 +18,8 @@ export async function generateCodeForPrompt(
context: { context: {
schema: Array<{ nodeName: string; schema: Schema }>; schema: Array<{ nodeName: string; schema: Schema }>;
inputSchema: { nodeName: string; schema: Schema }; inputSchema: { nodeName: string; schema: Schema };
sessionId: string; pushRef: string;
ndvSessionId: string; ndvPushRef: string;
}; };
model: string; model: string;
n8nVersion: string; n8nVersion: string;

View file

@ -165,8 +165,8 @@ async function onSubmit() {
context: { context: {
schema: schemas.parentNodesSchemas, schema: schemas.parentNodesSchemas,
inputSchema: schemas.inputSchema!, inputSchema: schemas.inputSchema!,
ndvSessionId: useNDVStore().sessionId, ndvPushRef: useNDVStore().pushRef,
sessionId: useRootStore().sessionId, pushRef: useRootStore().pushRef,
}, },
model, model,
n8nVersion: version, n8nVersion: version,

View file

@ -177,7 +177,7 @@ export default defineComponent({
this.segments, this.segments,
this.modelValue, this.modelValue,
this.workflowsStore.workflowId, this.workflowsStore.workflowId,
this.ndvStore.sessionId, this.ndvStore.pushRef,
this.ndvStore.activeNode?.type ?? '', this.ndvStore.activeNode?.type ?? '',
); );

View file

@ -82,7 +82,7 @@ function onBlur(event?: FocusEvent | KeyboardEvent) {
segments.value, segments.value,
props.modelValue, props.modelValue,
workflowsStore.workflowId, workflowsStore.workflowId,
ndvStore.sessionId, ndvStore.pushRef,
ndvStore.activeNode?.type ?? '', ndvStore.activeNode?.type ?? '',
); );

View file

@ -8,7 +8,7 @@
:no-data-in-branch-message="$locale.baseText('ndv.input.noOutputDataInBranch')" :no-data-in-branch-message="$locale.baseText('ndv.input.noOutputDataInBranch')"
:is-executing="isExecutingPrevious" :is-executing="isExecutingPrevious"
:executing-message="$locale.baseText('ndv.input.executingPrevious')" :executing-message="$locale.baseText('ndv.input.executingPrevious')"
:session-id="sessionId" :push-ref="pushRef"
:override-outputs="connectedCurrentNodeOutputs" :override-outputs="connectedCurrentNodeOutputs"
:mapping-enabled="isMappingEnabled" :mapping-enabled="isMappingEnabled"
:distance-from-active="currentNodeDepth" :distance-from-active="currentNodeDepth"
@ -208,7 +208,7 @@ export default defineComponent({
canLinkRuns: { canLinkRuns: {
type: Boolean, type: Boolean,
}, },
sessionId: { pushRef: {
type: String, type: String,
}, },
readOnly: { readOnly: {
@ -472,7 +472,7 @@ export default defineComponent({
this.$telemetry.track('User clicked ndv button', { this.$telemetry.track('User clicked ndv button', {
node_type: this.activeNode.type, node_type: this.activeNode.type,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
pane: 'input', pane: 'input',
type: 'executePrevious', type: 'executePrevious',
}); });
@ -496,7 +496,7 @@ export default defineComponent({
this.$telemetry.track('User clicked ndv link', { this.$telemetry.track('User clicked ndv link', {
node_type: this.activeNode.type, node_type: this.activeNode.type,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
pane: 'input', pane: 'input',
type: 'not-connected-help', type: 'not-connected-help',
}); });

View file

@ -55,7 +55,7 @@
<TriggerPanel <TriggerPanel
v-if="showTriggerPanel" v-if="showTriggerPanel"
:node-name="activeNode.name" :node-name="activeNode.name"
:session-id="sessionId" :push-ref="pushRef"
@execute="onNodeExecute" @execute="onNodeExecute"
@activate="onWorkflowActivate" @activate="onWorkflowActivate"
/> />
@ -66,7 +66,7 @@
:run-index="inputRun" :run-index="inputRun"
:linked-runs="linked" :linked-runs="linked"
:current-node-name="inputNodeName" :current-node-name="inputNodeName"
:session-id="sessionId" :push-ref="pushRef"
:read-only="readOnly || hasForeignCredential" :read-only="readOnly || hasForeignCredential"
:is-production-execution-preview="isProductionExecutionPreview" :is-production-execution-preview="isProductionExecutionPreview"
:is-pane-active="isInputPaneActive" :is-pane-active="isInputPaneActive"
@ -88,7 +88,7 @@
:can-link-runs="canLinkRuns" :can-link-runs="canLinkRuns"
:run-index="outputRun" :run-index="outputRun"
:linked-runs="linked" :linked-runs="linked"
:session-id="sessionId" :push-ref="pushRef"
:is-read-only="readOnly || hasForeignCredential" :is-read-only="readOnly || hasForeignCredential"
:block-u-i="blockUi && isTriggerNode && !isExecutableTriggerNode" :block-u-i="blockUi && isTriggerNode && !isExecutableTriggerNode"
:is-production-execution-preview="isProductionExecutionPreview" :is-production-execution-preview="isProductionExecutionPreview"
@ -107,7 +107,7 @@
<NodeSettings <NodeSettings
:event-bus="settingsEventBus" :event-bus="settingsEventBus"
:dragging="isDragging" :dragging="isDragging"
:session-id="sessionId" :push-ref="pushRef"
:node-type="activeNodeType" :node-type="activeNodeType"
:foreign-credentials="foreignCredentials" :foreign-credentials="foreignCredentials"
:read-only="readOnly" :read-only="readOnly"
@ -249,8 +249,8 @@ export default defineComponent({
}, },
computed: { computed: {
...mapStores(useNodeTypesStore, useNDVStore, useUIStore, useWorkflowsStore, useSettingsStore), ...mapStores(useNodeTypesStore, useNDVStore, useUIStore, useWorkflowsStore, useSettingsStore),
sessionId(): string { pushRef(): string {
return this.ndvStore.sessionId; return this.ndvStore.pushRef;
}, },
workflowRunning(): boolean { workflowRunning(): boolean {
return this.uiStore.isActionActive('workflowRunning'); return this.uiStore.isActionActive('workflowRunning');
@ -485,7 +485,7 @@ export default defineComponent({
this.avgOutputRowHeight = 0; this.avgOutputRowHeight = 0;
this.avgInputRowHeight = 0; this.avgInputRowHeight = 0;
setTimeout(() => this.ndvStore.setNDVSessionId(), 0); setTimeout(() => this.ndvStore.setNDVPushRef(), 0);
void this.externalHooks.run('dataDisplay.nodeTypeChanged', { void this.externalHooks.run('dataDisplay.nodeTypeChanged', {
nodeSubtitle: this.nodeHelpers.getNodeSubtitle( nodeSubtitle: this.nodeHelpers.getNodeSubtitle(
node, node,
@ -503,7 +503,7 @@ export default defineComponent({
this.$telemetry.track('User opened node modal', { this.$telemetry.track('User opened node modal', {
node_type: this.activeNodeType ? this.activeNodeType.name : '', node_type: this.activeNodeType ? this.activeNodeType.name : '',
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
is_editable: !this.hasForeignCredential, is_editable: !this.hasForeignCredential,
parameters_pane_position: this.mainPanelPosition, parameters_pane_position: this.mainPanelPosition,
input_first_connector_runs: this.maxInputRun, input_first_connector_runs: this.maxInputRun,
@ -604,7 +604,7 @@ export default defineComponent({
this.$telemetry.track('User clicked ndv link', { this.$telemetry.track('User clicked ndv link', {
node_type: this.activeNode.type, node_type: this.activeNode.type,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
pane: NodeConnectionType.Main, pane: NodeConnectionType.Main,
type: 'i-wish-this-node-would', type: 'i-wish-this-node-would',
}); });
@ -624,7 +624,7 @@ export default defineComponent({
start_position: this.mainPanelPosition, start_position: this.mainPanelPosition,
end_position: e.position, end_position: e.position,
node_type: this.activeNodeType ? this.activeNodeType.name : '', node_type: this.activeNodeType ? this.activeNodeType.name : '',
session_id: this.sessionId, push_ref: this.pushRef,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
}); });
this.mainPanelPosition = e.position; this.mainPanelPosition = e.position;
@ -646,7 +646,7 @@ export default defineComponent({
trackLinking(pane: string) { trackLinking(pane: string) {
this.$telemetry.track('User changed ndv run linking', { this.$telemetry.track('User changed ndv run linking', {
node_type: this.activeNodeType ? this.activeNodeType.name : '', node_type: this.activeNodeType ? this.activeNodeType.name : '',
session_id: this.sessionId, push_ref: this.pushRef,
linked: this.linked, linked: this.linked,
pane, pane,
}); });
@ -719,12 +719,12 @@ export default defineComponent({
await this.externalHooks.run('dataDisplay.nodeEditingFinished'); await this.externalHooks.run('dataDisplay.nodeEditingFinished');
this.$telemetry.track('User closed node modal', { this.$telemetry.track('User closed node modal', {
node_type: this.activeNodeType ? this.activeNodeType.name : '', node_type: this.activeNodeType ? this.activeNodeType.name : '',
session_id: this.sessionId, push_ref: this.pushRef,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
}); });
this.triggerWaitingWarningEnabled = false; this.triggerWaitingWarningEnabled = false;
this.ndvStore.activeNodeName = null; this.ndvStore.activeNodeName = null;
this.ndvStore.resetNDVSessionId(); this.ndvStore.resetNDVPushRef();
}, },
onRunOutputIndexChange(run: number) { onRunOutputIndexChange(run: number) {
this.runOutputIndex = run; this.runOutputIndex = run;
@ -739,7 +739,7 @@ export default defineComponent({
}, },
trackRunChange(run: number, pane: string) { trackRunChange(run: number, pane: string) {
this.$telemetry.track('User changed ndv run dropdown', { this.$telemetry.track('User changed ndv run dropdown', {
session_id: this.sessionId, push_ref: this.pushRef,
run_index: run, run_index: run,
node_type: this.activeNodeType ? this.activeNodeType.name : '', node_type: this.activeNodeType ? this.activeNodeType.name : '',
pane, pane,
@ -752,7 +752,7 @@ export default defineComponent({
this.$telemetry.track('User changed ndv input dropdown', { this.$telemetry.track('User changed ndv input dropdown', {
node_type: this.activeNode ? this.activeNode.type : '', node_type: this.activeNode ? this.activeNode.type : '',
session_id: this.sessionId, push_ref: this.pushRef,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
selection_value: index, selection_value: index,
input_node_type: this.inputNode ? this.inputNode.type : '', input_node_type: this.inputNode ? this.inputNode.type : '',

View file

@ -263,7 +263,7 @@ export default defineComponent({
node_type: this.nodeType ? this.nodeType.name : null, node_type: this.nodeType ? this.nodeType.name : null,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
source: this.telemetrySource, source: this.telemetrySource,
session_id: this.ndvStore.sessionId, push_ref: this.ndvStore.pushRef,
}; };
this.$telemetry.track('User clicked execute node button', telemetryPayload); this.$telemetry.track('User clicked execute node button', telemetryPayload);
await this.externalHooks.run('nodeExecuteButton.onClick', telemetryPayload); await this.externalHooks.run('nodeExecuteButton.onClick', telemetryPayload);

View file

@ -33,7 +33,7 @@
v-if="node && nodeValid" v-if="node && nodeValid"
v-model="openPanel" v-model="openPanel"
:node-type="nodeType" :node-type="nodeType"
:session-id="sessionId" :push-ref="pushRef"
/> />
</div> </div>
<div v-if="node && !nodeValid" class="node-is-not-valid"> <div v-if="node && !nodeValid" class="node-is-not-valid">
@ -389,7 +389,7 @@ export default defineComponent({
dragging: { dragging: {
type: Boolean, type: Boolean,
}, },
sessionId: { pushRef: {
type: String, type: String,
}, },
nodeType: { nodeType: {

View file

@ -32,7 +32,7 @@ export default defineComponent({
default: '', default: '',
}, },
nodeType: {}, nodeType: {},
sessionId: { pushRef: {
type: String, type: String,
}, },
}, },
@ -135,7 +135,7 @@ export default defineComponent({
this.$telemetry.track('User clicked ndv link', { this.$telemetry.track('User clicked ndv link', {
node_type: this.activeNode.type, node_type: this.activeNode.type,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
pane: NodeConnectionType.Main, pane: NodeConnectionType.Main,
type: 'docs', type: 'docs',
}); });

View file

@ -9,7 +9,7 @@
:no-data-in-branch-message="$locale.baseText('ndv.output.noOutputDataInBranch')" :no-data-in-branch-message="$locale.baseText('ndv.output.noOutputDataInBranch')"
:is-executing="isNodeRunning" :is-executing="isNodeRunning"
:executing-message="$locale.baseText('ndv.output.executing')" :executing-message="$locale.baseText('ndv.output.executing')"
:session-id="sessionId" :push-ref="pushRef"
:block-u-i="blockUI" :block-u-i="blockUI"
:is-production-execution-preview="isProductionExecutionPreview" :is-production-execution-preview="isProductionExecutionPreview"
:is-pane-active="isPaneActive" :is-pane-active="isPaneActive"
@ -139,7 +139,7 @@ export default defineComponent({
canLinkRuns: { canLinkRuns: {
type: Boolean, type: Boolean,
}, },
sessionId: { pushRef: {
type: String, type: String,
}, },
blockUI: { blockUI: {
@ -300,7 +300,7 @@ export default defineComponent({
this.$telemetry.track('User clicked ndv link', { this.$telemetry.track('User clicked ndv link', {
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
node_type: this.node.type, node_type: this.node.type,
pane: 'output', pane: 'output',
type: 'insert-test-data', type: 'insert-test-data',
@ -318,7 +318,7 @@ export default defineComponent({
this.$telemetry.track('User clicked ndv link', { this.$telemetry.track('User clicked ndv link', {
node_type: this.node.type, node_type: this.node.type,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
pane: 'output', pane: 'output',
type: 'settings', type: 'settings',
}); });

View file

@ -1145,7 +1145,7 @@ export default defineComponent({
parameter_field_type: this.parameter.type, parameter_field_type: this.parameter.type,
new_expression: !this.isValueExpression, new_expression: !this.isValueExpression,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.ndvStore.sessionId, push_ref: this.ndvStore.pushRef,
source: this.eventSource || 'ndv', source: this.eventSource || 'ndv',
}); });
} }
@ -1297,7 +1297,7 @@ export default defineComponent({
node_type: this.node && this.node.type, node_type: this.node && this.node.type,
resource: this.node && this.node.parameters.resource, resource: this.node && this.node.parameters.resource,
is_custom: value === CUSTOM_API_CALL_KEY, is_custom: value === CUSTOM_API_CALL_KEY,
session_id: this.ndvStore.sessionId, push_ref: this.ndvStore.pushRef,
parameter: this.parameter.name, parameter: this.parameter.name,
}); });
} }

View file

@ -382,7 +382,7 @@
<RunDataJson <RunDataJson
:pane-type="paneType" :pane-type="paneType"
:edit-mode="editMode" :edit-mode="editMode"
:sessio-id="sessionId" :push-ref="pushRef"
:node="node" :node="node"
:input-data="inputDataPage" :input-data="inputDataPage"
:mapping-enabled="mappingEnabled" :mapping-enabled="mappingEnabled"
@ -658,7 +658,7 @@ export default defineComponent({
executingMessage: { executingMessage: {
type: String, type: String,
}, },
sessionId: { pushRef: {
type: String, type: String,
}, },
paneType: { paneType: {
@ -1062,7 +1062,7 @@ export default defineComponent({
onClickDataPinningDocsLink() { onClickDataPinningDocsLink() {
this.$telemetry.track('User clicked ndv link', { this.$telemetry.track('User clicked ndv link', {
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
node_type: this.activeNode?.type, node_type: this.activeNode?.type,
pane: 'output', pane: 'output',
type: 'data-pinning-docs', type: 'data-pinning-docs',
@ -1109,7 +1109,7 @@ export default defineComponent({
this.$telemetry.track('User opened ndv edit state', { this.$telemetry.track('User opened ndv edit state', {
node_type: this.activeNode?.type, node_type: this.activeNode?.type,
click_type: origin === 'editIconButton' ? 'button' : 'link', click_type: origin === 'editIconButton' ? 'button' : 'link',
session_id: this.sessionId, push_ref: this.pushRef,
run_index: this.runIndex, run_index: this.runIndex,
is_output_present: this.hasNodeRun || this.pinnedData.hasData.value, is_output_present: this.hasNodeRun || this.pinnedData.hasData.value,
view: !this.hasNodeRun && !this.pinnedData.hasData.value ? 'undefined' : this.displayMode, view: !this.hasNodeRun && !this.pinnedData.hasData.value ? 'undefined' : this.displayMode,
@ -1144,7 +1144,7 @@ export default defineComponent({
onExitEditMode({ type }: { type: 'save' | 'cancel' }) { onExitEditMode({ type }: { type: 'save' | 'cancel' }) {
this.$telemetry.track('User closed ndv edit state', { this.$telemetry.track('User closed ndv edit state', {
node_type: this.activeNode?.type, node_type: this.activeNode?.type,
session_id: this.sessionId, push_ref: this.pushRef,
run_index: this.runIndex, run_index: this.runIndex,
view: this.displayMode, view: this.displayMode,
type, type,
@ -1158,7 +1158,7 @@ export default defineComponent({
if (source === 'pin-icon-click') { if (source === 'pin-icon-click') {
const telemetryPayload = { const telemetryPayload = {
node_type: this.activeNode.type, node_type: this.activeNode.type,
session_id: this.sessionId, push_ref: this.pushRef,
run_index: this.runIndex, run_index: this.runIndex,
view: !this.hasNodeRun && !this.pinnedData.hasData.value ? 'none' : this.displayMode, view: !this.hasNodeRun && !this.pinnedData.hasData.value ? 'none' : this.displayMode,
}; };
@ -1204,7 +1204,7 @@ export default defineComponent({
this.outputIndex = value; this.outputIndex = value;
this.$telemetry.track('User changed ndv branch', { this.$telemetry.track('User changed ndv branch', {
session_id: this.sessionId, push_ref: this.pushRef,
branch_index: value, branch_index: value,
node_type: this.activeNode.type, node_type: this.activeNode.type,
node_type_input_selection: this.nodeType ? this.nodeType.name : '', node_type_input_selection: this.nodeType ? this.nodeType.name : '',
@ -1216,7 +1216,7 @@ export default defineComponent({
this.$telemetry.track('User clicked ndv button', { this.$telemetry.track('User clicked ndv button', {
node_type: this.activeNode.type, node_type: this.activeNode.type,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
pane: this.paneType, pane: this.paneType,
type: 'showTooMuchData', type: 'showTooMuchData',
}); });
@ -1235,7 +1235,7 @@ export default defineComponent({
this.$telemetry.track('User changed ndv page', { this.$telemetry.track('User changed ndv page', {
node_type: this.activeNode?.type, node_type: this.activeNode?.type,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
pane: this.paneType, pane: this.paneType,
page_selected: this.currentPage, page_selected: this.currentPage,
page_size: this.pageSize, page_size: this.pageSize,
@ -1252,7 +1252,7 @@ export default defineComponent({
this.$telemetry.track('User changed ndv page size', { this.$telemetry.track('User changed ndv page size', {
node_type: this.activeNode?.type, node_type: this.activeNode?.type,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
pane: this.paneType, pane: this.paneType,
page_selected: this.currentPage, page_selected: this.currentPage,
page_size: this.pageSize, page_size: this.pageSize,
@ -1283,7 +1283,7 @@ export default defineComponent({
new_view: displayMode, new_view: displayMode,
node_type: this.activeNode.type, node_type: this.activeNode.type,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
pane: this.paneType, pane: this.paneType,
}); });
} }

View file

@ -4,7 +4,7 @@
<RunDataJsonActions <RunDataJsonActions
v-if="!editMode.enabled" v-if="!editMode.enabled"
:node="node" :node="node"
:sessio-id="sessionId" :push-ref="pushRef"
:display-mode="displayMode" :display-mode="displayMode"
:distance-from-active="distanceFromActive" :distance-from-active="distanceFromActive"
:selected-json-path="selectedJsonPath" :selected-json-path="selectedJsonPath"
@ -110,7 +110,7 @@ export default defineComponent({
editMode: { editMode: {
type: Object as () => { enabled?: boolean; value?: string }, type: Object as () => { enabled?: boolean; value?: string },
}, },
sessionId: { pushRef: {
type: String, type: String,
}, },
paneType: { paneType: {

View file

@ -68,7 +68,7 @@ export default defineComponent({
paneType: { paneType: {
type: String, type: String,
}, },
sessionId: { pushRef: {
type: String, type: String,
}, },
currentOutputIndex: { currentOutputIndex: {
@ -222,7 +222,7 @@ export default defineComponent({
this.$telemetry.track('User copied ndv data', { this.$telemetry.track('User copied ndv data', {
node_type: this.activeNode.type, node_type: this.activeNode.type,
session_id: this.sessionId, push_ref: this.pushRef,
run_index: this.runIndex, run_index: this.runIndex,
view: 'json', view: 'json',
copy_type: copyType, copy_type: copyType,

View file

@ -142,7 +142,7 @@ export default defineComponent({
nodeName: { nodeName: {
type: String, type: String,
}, },
sessionId: { pushRef: {
type: String, type: String,
}, },
}, },
@ -409,7 +409,7 @@ export default defineComponent({
openWebhookUrl() { openWebhookUrl() {
this.$telemetry.track('User clicked ndv link', { this.$telemetry.track('User clicked ndv link', {
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
pane: 'input', pane: 'input',
type: 'open-chat', type: 'open-chat',
}); });
@ -431,7 +431,7 @@ export default defineComponent({
} else if (target.dataset.key === 'executions') { } else if (target.dataset.key === 'executions') {
this.$telemetry.track('User clicked ndv link', { this.$telemetry.track('User clicked ndv link', {
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId, push_ref: this.pushRef,
pane: 'input', pane: 'input',
type: 'open-executions-log', type: 'open-executions-log',
}); });

View file

@ -465,7 +465,7 @@ export default defineComponent({
[ [
{ {
json: { json: {
sessionId: `test-${currentUser.id || 'unknown'}`, pushRef: `test-${currentUser.id || 'unknown'}`,
action: 'sendMessage', action: 'sendMessage',
[inputKey]: message, [inputKey]: message,
}, },

View file

@ -48,7 +48,7 @@ export function usePinnedData(
const telemetry = useTelemetry(); const telemetry = useTelemetry();
const externalHooks = useExternalHooks(); const externalHooks = useExternalHooks();
const { sessionId } = storeToRefs(rootStore); const { pushRef } = storeToRefs(rootStore);
const { isSubNodeType, isMultipleOutputsNodeType } = useNodeType({ const { isSubNodeType, isMultipleOutputsNodeType } = useNodeType({
node, node,
}); });
@ -163,7 +163,7 @@ export function usePinnedData(
const telemetryPayload = { const telemetryPayload = {
pinning_source: source, pinning_source: source,
node_type: targetNode?.type, node_type: targetNode?.type,
session_id: sessionId.value, push_ref: pushRef.value,
data_size: stringSizeInBytes(data.value), data_size: stringSizeInBytes(data.value),
view: displayMode, view: displayMode,
run_index: runIndex, run_index: runIndex,
@ -187,7 +187,7 @@ export function usePinnedData(
telemetry.track('Ndv data pinning failure', { telemetry.track('Ndv data pinning failure', {
pinning_source: source, pinning_source: source,
node_type: targetNode?.type, node_type: targetNode?.type,
session_id: sessionId.value, push_ref: pushRef.value,
data_size: stringSizeInBytes(data.value), data_size: stringSizeInBytes(data.value),
view: displayMode, view: displayMode,
run_index: runIndex, run_index: runIndex,
@ -225,7 +225,7 @@ export function usePinnedData(
telemetry.track('User unpinned ndv data', { telemetry.track('User unpinned ndv data', {
node_type: targetNode?.type, node_type: targetNode?.type,
session_id: sessionId.value, push_ref: pushRef.value,
run_index: runIndex, run_index: runIndex,
source, source,
data_size: stringSizeInBytes(data.value), data_size: stringSizeInBytes(data.value),

View file

@ -46,7 +46,7 @@ export const n8nCloudHooks: PartialDeep<ExternalHooks> = {
const segmentStore = useSegment(); const segmentStore = useSegment();
const eventData = { const eventData = {
source: meta.source, source: meta.source,
nodes_panel_session_id: nodesPanelSession.sessionId, nodes_panel_session_id: nodesPanelSession.pushRef,
}; };
hooksResetNodesPanelSession(); hooksResetNodesPanelSession();
@ -61,7 +61,7 @@ export const n8nCloudHooks: PartialDeep<ExternalHooks> = {
eventName: 'User added node to workflow canvas', eventName: 'User added node to workflow canvas',
properties: { properties: {
node_type: meta.nodeTypeName.split('.')[1], node_type: meta.nodeTypeName.split('.')[1],
nodes_panel_session_id: nodesPanelSession.sessionId, nodes_panel_session_id: nodesPanelSession.pushRef,
}, },
}; };
@ -473,7 +473,7 @@ export const n8nCloudHooks: PartialDeep<ExternalHooks> = {
properties: { properties: {
old_filter: meta.oldValue, old_filter: meta.oldValue,
new_filter: meta.newValue, new_filter: meta.newValue,
nodes_panel_session_id: nodesPanelSession.sessionId, nodes_panel_session_id: nodesPanelSession.pushRef,
}, },
}; };
nodesPanelSession.data.filterMode = meta.newValue; nodesPanelSession.data.filterMode = meta.newValue;

View file

@ -1,5 +1,5 @@
export const nodesPanelSession = { export const nodesPanelSession = {
sessionId: '', pushRef: '',
data: { data: {
nodeFilter: '', nodeFilter: '',
resultsNodes: [] as string[], resultsNodes: [] as string[],
@ -15,13 +15,13 @@ export const hooksGenerateNodesPanelEvent = () => {
results_count: nodesPanelSession.data.resultsNodes.length, results_count: nodesPanelSession.data.resultsNodes.length,
results_nodes: nodesPanelSession.data.resultsNodes, results_nodes: nodesPanelSession.data.resultsNodes,
filter_mode: nodesPanelSession.data.filterMode, filter_mode: nodesPanelSession.data.filterMode,
nodes_panel_session_id: nodesPanelSession.sessionId, nodes_panel_session_id: nodesPanelSession.pushRef,
}, },
}; };
}; };
export const hooksResetNodesPanelSession = () => { export const hooksResetNodesPanelSession = () => {
nodesPanelSession.sessionId = `nodes_panel_session_${new Date().valueOf()}`; nodesPanelSession.pushRef = `nodes_panel_session_${new Date().valueOf()}`;
nodesPanelSession.data = { nodesPanelSession.data = {
nodeFilter: '', nodeFilter: '',
resultsNodes: [], resultsNodes: [],

View file

@ -82,8 +82,8 @@ export const pushConnection = defineComponent({
usePushConnectionStore, usePushConnectionStore,
useCollaborationStore, useCollaborationStore,
), ),
sessionId(): string { pushRef(): string {
return this.rootStore.sessionId; return this.rootStore.pushRef;
}, },
}, },
methods: { methods: {

View file

@ -27,7 +27,7 @@ export class Telemetry {
} }
private userNodesPanelSession: IUserNodesPanelSession = { private userNodesPanelSession: IUserNodesPanelSession = {
sessionId: '', pushRef: '',
data: { data: {
nodeFilter: '', nodeFilter: '',
resultsNodes: [], resultsNodes: [],
@ -76,7 +76,7 @@ export class Telemetry {
this.identify(instanceId, userId, versionCli); this.identify(instanceId, userId, versionCli);
this.flushPageEvents(); this.flushPageEvents();
this.track('Session started', { session_id: rootStore.sessionId }); this.track('Session started', { session_id: rootStore.pushRef });
} }
identify(instanceId: string, userId?: string, versionCli?: string) { identify(instanceId: string, userId?: string, versionCli?: string) {
@ -150,8 +150,8 @@ export class Telemetry {
trackAskAI(event: string, properties: IDataObject = {}) { trackAskAI(event: string, properties: IDataObject = {}) {
if (this.rudderStack) { if (this.rudderStack) {
properties.session_id = useRootStore().sessionId; properties.session_id = useRootStore().pushRef;
properties.ndv_session_id = useNDVStore().sessionId; properties.ndv_session_id = useNDVStore().pushRef;
switch (event) { switch (event) {
case 'askAi.generationFinished': case 'askAi.generationFinished':
@ -164,12 +164,12 @@ export class Telemetry {
trackNodesPanel(event: string, properties: IDataObject = {}) { trackNodesPanel(event: string, properties: IDataObject = {}) {
if (this.rudderStack) { if (this.rudderStack) {
properties.nodes_panel_session_id = this.userNodesPanelSession.sessionId; properties.nodes_panel_session_id = this.userNodesPanelSession.pushRef;
switch (event) { switch (event) {
case 'nodeView.createNodeActiveChanged': case 'nodeView.createNodeActiveChanged':
if (properties.createNodeActive !== false) { if (properties.createNodeActive !== false) {
this.resetNodesPanelSession(); this.resetNodesPanelSession();
properties.nodes_panel_session_id = this.userNodesPanelSession.sessionId; properties.nodes_panel_session_id = this.userNodesPanelSession.pushRef;
this.track('User opened nodes panel', properties); this.track('User opened nodes panel', properties);
} }
break; break;
@ -200,25 +200,25 @@ export class Telemetry {
break; break;
case 'nodeCreateList.onCategoryExpanded': case 'nodeCreateList.onCategoryExpanded':
properties.is_subcategory = false; properties.is_subcategory = false;
properties.nodes_panel_session_id = this.userNodesPanelSession.sessionId; properties.nodes_panel_session_id = this.userNodesPanelSession.pushRef;
this.track('User viewed node category', properties); this.track('User viewed node category', properties);
break; break;
case 'nodeCreateList.onViewActions': case 'nodeCreateList.onViewActions':
properties.nodes_panel_session_id = this.userNodesPanelSession.sessionId; properties.nodes_panel_session_id = this.userNodesPanelSession.pushRef;
this.track('User viewed node actions', properties); this.track('User viewed node actions', properties);
break; break;
case 'nodeCreateList.onActionsCustmAPIClicked': case 'nodeCreateList.onActionsCustmAPIClicked':
properties.nodes_panel_session_id = this.userNodesPanelSession.sessionId; properties.nodes_panel_session_id = this.userNodesPanelSession.pushRef;
this.track('User clicked custom API from node actions', properties); this.track('User clicked custom API from node actions', properties);
break; break;
case 'nodeCreateList.addAction': case 'nodeCreateList.addAction':
properties.nodes_panel_session_id = this.userNodesPanelSession.sessionId; properties.nodes_panel_session_id = this.userNodesPanelSession.pushRef;
this.track('User added action', properties); this.track('User added action', properties);
break; break;
case 'nodeCreateList.onSubcategorySelected': case 'nodeCreateList.onSubcategorySelected':
properties.category_name = properties.subcategory; properties.category_name = properties.subcategory;
properties.is_subcategory = true; properties.is_subcategory = true;
properties.nodes_panel_session_id = this.userNodesPanelSession.sessionId; properties.nodes_panel_session_id = this.userNodesPanelSession.pushRef;
delete properties.selected; delete properties.selected;
this.track('User viewed node category', properties); this.track('User viewed node category', properties);
break; break;
@ -258,7 +258,7 @@ export class Telemetry {
} }
private resetNodesPanelSession() { private resetNodesPanelSession() {
this.userNodesPanelSession.sessionId = `nodes_panel_session_${new Date().valueOf()}`; this.userNodesPanelSession.pushRef = `nodes_panel_session_${new Date().valueOf()}`;
this.userNodesPanelSession.data = { this.userNodesPanelSession.data = {
nodeFilter: '', nodeFilter: '',
resultsNodes: [], resultsNodes: [],
@ -271,7 +271,7 @@ export class Telemetry {
search_string: this.userNodesPanelSession.data.nodeFilter, search_string: this.userNodesPanelSession.data.nodeFilter,
results_count: this.userNodesPanelSession.data.resultsNodes.length, results_count: this.userNodesPanelSession.data.resultsNodes.length,
filter_mode: this.userNodesPanelSession.data.filterMode, filter_mode: this.userNodesPanelSession.data.filterMode,
nodes_panel_session_id: this.userNodesPanelSession.sessionId, nodes_panel_session_id: this.userNodesPanelSession.pushRef,
}; };
} }

View file

@ -5,7 +5,7 @@ declare global {
} }
export interface IUserNodesPanelSession { export interface IUserNodesPanelSession {
sessionId: string; pushRef: string;
data: IUserNodesPanelSessionData; data: IUserNodesPanelSessionData;
} }

View file

@ -105,7 +105,7 @@ export const useCloudPlanStore = defineStore(STORES.CLOUD_PLAN, () => {
}; };
const getInstanceCurrentUsage = async () => { const getInstanceCurrentUsage = async () => {
const usage = await getCurrentUsage({ baseUrl: rootStore.getBaseUrl, sessionId: '' }); const usage = await getCurrentUsage({ baseUrl: rootStore.getBaseUrl, pushRef: '' });
state.usage = usage; state.usage = usage;
return usage; return usage;
}; };

View file

@ -25,7 +25,7 @@ export const useRootStore = defineStore(STORES.ROOT, {
versionCli: '0.0.0', versionCli: '0.0.0',
oauthCallbackUrls: {}, oauthCallbackUrls: {},
n8nMetadata: {}, n8nMetadata: {},
sessionId: Math.random().toString(36).substring(2, 15), pushRef: Math.random().toString(36).substring(2, 15),
urlBaseWebhook: 'http://localhost:5678/', urlBaseWebhook: 'http://localhost:5678/',
urlBaseEditor: 'http://localhost:5678', urlBaseEditor: 'http://localhost:5678',
isNpmAvailable: false, isNpmAvailable: false,
@ -66,14 +66,14 @@ export const useRootStore = defineStore(STORES.ROOT, {
baseUrl: window.location.host.includes('stage-app.n8n.cloud') baseUrl: window.location.host.includes('stage-app.n8n.cloud')
? CLOUD_BASE_URL_STAGING ? CLOUD_BASE_URL_STAGING
: CLOUD_BASE_URL_PRODUCTION, : CLOUD_BASE_URL_PRODUCTION,
sessionId: '', pushRef: '',
}; };
}, },
getRestApiContext(): IRestApiContext { getRestApiContext(): IRestApiContext {
return { return {
baseUrl: this.getRestUrl, baseUrl: this.getRestUrl,
sessionId: this.sessionId, pushRef: this.pushRef,
}; };
}, },
}, },

View file

@ -22,7 +22,7 @@ export const useNDVStore = defineStore(STORES.NDV, {
state: (): NDVState => ({ state: (): NDVState => ({
activeNodeName: null, activeNodeName: null,
mainPanelDimensions: {}, mainPanelDimensions: {},
sessionId: '', pushRef: '',
input: { input: {
displayMode: 'schema', displayMode: 'schema',
nodeName: undefined, nodeName: undefined,
@ -184,11 +184,11 @@ export const useNDVStore = defineStore(STORES.NDV, {
}, },
}; };
}, },
setNDVSessionId(): void { setNDVPushRef(): void {
this.sessionId = `ndv-${uuid()}`; this.pushRef = `ndv-${uuid()}`;
}, },
resetNDVSessionId(): void { resetNDVPushRef(): void {
this.sessionId = ''; this.pushRef = '';
}, },
setPanelDisplayMode(params: { pane: NodePanelType; mode: IRunDataDisplayMode }): void { setPanelDisplayMode(params: { pane: NodePanelType; mode: IRunDataDisplayMode }): void {
this[params.pane].displayMode = params.mode; this[params.pane].displayMode = params.mode;

View file

@ -6,7 +6,7 @@ import { useRootStore } from './n8nRoot.store';
import type { IPushData } from '../Interface'; import type { IPushData } from '../Interface';
export interface PushState { export interface PushState {
sessionId: string; pushRef: string;
pushSource: WebSocket | EventSource | null; pushSource: WebSocket | EventSource | null;
reconnectTimeout: NodeJS.Timeout | null; reconnectTimeout: NodeJS.Timeout | null;
retryTimeout: NodeJS.Timeout | null; retryTimeout: NodeJS.Timeout | null;
@ -26,7 +26,7 @@ export const usePushConnectionStore = defineStore(STORES.PUSH, () => {
const rootStore = useRootStore(); const rootStore = useRootStore();
const settingsStore = useSettingsStore(); const settingsStore = useSettingsStore();
const sessionId = computed(() => rootStore.sessionId); const pushRef = computed(() => rootStore.pushRef);
const pushSource = ref<WebSocket | EventSource | null>(null); const pushSource = ref<WebSocket | EventSource | null>(null);
const reconnectTimeout = ref<NodeJS.Timeout | null>(null); const reconnectTimeout = ref<NodeJS.Timeout | null>(null);
const connectRetries = ref(0); const connectRetries = ref(0);
@ -85,7 +85,7 @@ export const usePushConnectionStore = defineStore(STORES.PUSH, () => {
const useWebSockets = settingsStore.pushBackend === 'websocket'; const useWebSockets = settingsStore.pushBackend === 'websocket';
const { getRestUrl: restUrl } = rootStore; const { getRestUrl: restUrl } = rootStore;
const url = `/push?sessionId=${sessionId.value}`; const url = `/push?pushRef=${pushRef.value}`;
if (useWebSockets) { if (useWebSockets) {
const { protocol, host } = window.location; const { protocol, host } = window.location;
@ -151,7 +151,7 @@ export const usePushConnectionStore = defineStore(STORES.PUSH, () => {
} }
return { return {
sessionId, pushRef,
pushSource, pushSource,
isConnectionOpen, isConnectionOpen,
addEventListener, addEventListener,

View file

@ -125,7 +125,7 @@ export async function makeRestApiRequest<T>(
method, method,
baseURL: context.baseUrl, baseURL: context.baseUrl,
endpoint, endpoint,
headers: { sessionid: context.sessionId }, headers: { 'push-ref': context.pushRef },
data, data,
}); });

View file

@ -6,7 +6,7 @@ export function createExpressionTelemetryPayload(
segments: Segment[], segments: Segment[],
value: string, value: string,
workflowId: string, workflowId: string,
sessionId: string, pushRef: string,
activeNodeType: string, activeNodeType: string,
eventSource = 'ndv', eventSource = 'ndv',
) { ) {
@ -17,7 +17,7 @@ export function createExpressionTelemetryPayload(
empty_expression: value === '=' || value === '={{}}' || !value, empty_expression: value === '=' || value === '={{}}' || !value,
workflow_id: workflowId, workflow_id: workflowId,
source: eventSource, source: eventSource,
session_id: sessionId, push_ref: pushRef,
is_transforming_data: resolvables.some((r) => isTransformingData(r.resolvable)), is_transforming_data: resolvables.some((r) => isTransformingData(r.resolvable)),
has_parameter: value.includes('$parameter'), has_parameter: value.includes('$parameter'),
has_mapping: hasExpressionMapping(value), has_mapping: hasExpressionMapping(value),

View file

@ -1066,7 +1066,7 @@ export default defineComponent({
node_type: node ? node.type : null, node_type: node ? node.type : null,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
source: 'canvas', source: 'canvas',
session_id: this.ndvStore.sessionId, push_ref: this.ndvStore.pushRef,
}; };
this.$telemetry.track('User clicked execute node button', telemetryPayload); this.$telemetry.track('User clicked execute node button', telemetryPayload);
void this.externalHooks.run('nodeView.onRunNode', telemetryPayload); void this.externalHooks.run('nodeView.onRunNode', telemetryPayload);

View file

@ -2102,7 +2102,7 @@ export type WorkflowActivateMode =
export interface IWorkflowHooksOptionalParameters { export interface IWorkflowHooksOptionalParameters {
retryOf?: string; retryOf?: string;
sessionId?: string; pushRef?: string;
} }
export namespace WorkflowSettings { export namespace WorkflowSettings {

View file

@ -12,7 +12,7 @@ export class WorkflowHooks {
executionId: string; executionId: string;
sessionId?: string; pushRef?: string;
retryOf?: string; retryOf?: string;
@ -32,7 +32,7 @@ export class WorkflowHooks {
this.mode = mode; this.mode = mode;
this.executionId = executionId; this.executionId = executionId;
this.workflowData = workflowData; this.workflowData = workflowData;
this.sessionId = optionalParameters.sessionId; this.pushRef = optionalParameters.pushRef;
// retryOf might be `null` from TypeORM // retryOf might be `null` from TypeORM
this.retryOf = optionalParameters.retryOf ?? undefined; this.retryOf = optionalParameters.retryOf ?? undefined;
} }