diff --git a/packages/pieces/common/package.json b/packages/pieces/common/package.json index 0b4fdfeca855..bf4944d7dee5 100644 --- a/packages/pieces/common/package.json +++ b/packages/pieces/common/package.json @@ -1,6 +1,6 @@ { "name": "@activepieces/pieces-common", - "version": "0.12.8", + "version": "0.12.9", "type": "commonjs", "sideEffects": false, "main": "./dist/src/index.js", diff --git a/packages/pieces/common/src/lib/helpers/index.ts b/packages/pieces/common/src/lib/helpers/index.ts index 5b9776e187ce..2b7af46ec397 100644 --- a/packages/pieces/common/src/lib/helpers/index.ts +++ b/packages/pieces/common/src/lib/helpers/index.ts @@ -1,4 +1,5 @@ import { + ActionClassification, OAuth2PropertyValue, PieceAuthProperty, Property, @@ -148,6 +149,7 @@ export function createCustomApiCallAction< props, extraProps, authLocation = 'headers', + classification = 'WRITE', }: { auth?: PieceAuth; baseUrl: BaseUrlGetter; @@ -172,10 +174,13 @@ export function createCustomApiCallAction< }; extraProps?: InputPropertyMap; authLocation?: 'headers' | 'queryParams'; + // The method is caller-supplied at runtime, so a single tag has to assume mutation. + classification?: ActionClassification; }) { return createAction({ audience: 'human', name: name ? name : 'custom_api_call', + classification, displayName: displayName ? displayName : 'Custom API Call', description: description ? description diff --git a/packages/server/api/src/app/ee/platform/platform-teardown-jobs.ts b/packages/server/api/src/app/ee/platform/platform-teardown-jobs.ts index a2062ad35afd..608d5b0eb3b0 100644 --- a/packages/server/api/src/app/ee/platform/platform-teardown-jobs.ts +++ b/packages/server/api/src/app/ee/platform/platform-teardown-jobs.ts @@ -1,4 +1,4 @@ -import { isNil, unique } from '@activepieces/core-utils' +import { isNil, tryCatch, unique } from '@activepieces/core-utils' import { Flow, FlowOperationType, FlowStatus, UserStatus } from '@activepieces/shared' import { FastifyBaseLogger } from 'fastify' import { IsNull } from 'typeorm' @@ -18,6 +18,7 @@ import { PieceMetadataEntity } from '../../pieces/metadata/piece-metadata-entity import { PlatformEntity } from '../../platform/platform.entity' import { ProjectEntity } from '../../project/project-entity' import { ToolSearchIndexEntity } from '../../tool-search/tool-search-index.entity' +import { triggerSourceService } from '../../trigger/trigger-source/trigger-source-service' import { userRepo } from '../../user/user-service' import { userInvitationRepo } from '../../user-invitations/user-invitation.service' import { VariableEntity } from '../../variable/variable.entity' @@ -41,7 +42,7 @@ export const platformTeardownJobs = (log: FastifyBaseLogger) => ({ hardDeletePlatformHandler: async (data: SystemJobData) => { const { platformId } = data - await cutOffPlatformAccess({ platformId, log }) + await beginPlatformTeardown({ platformId, log }) const flows = await listFlowsByPlatform(platformId) await drainFlows({ flows, log }) @@ -79,19 +80,19 @@ export const platformTeardownJobs = (log: FastifyBaseLogger) => ({ }, }) -export async function cutOffPlatformAccess({ platformId, log }: CutOffPlatformAccessParams): Promise { +export async function beginPlatformTeardown({ platformId, log }: BeginPlatformTeardownParams): Promise { await userRepo().update({ platformId }, { status: UserStatus.INACTIVE }) await apiKeyService.deleteAllByPlatformId({ platformId }) await stopPlatformExecution({ platformId, log }) } -async function stopPlatformExecution({ platformId, log }: CutOffPlatformAccessParams): Promise { +async function stopPlatformExecution({ platformId, log }: BeginPlatformTeardownParams): Promise { const flows = await listFlowsByPlatform(platformId) for (const flow of flows) { if (flow.status === FlowStatus.DISABLED || isNil(flow.publishedVersionId)) { continue } - await flowService(log).update({ + const { error } = await tryCatch(async () => flowService(log).update({ id: flow.id, userId: null, projectId: flow.projectId, @@ -101,7 +102,32 @@ async function stopPlatformExecution({ platformId, log }: CutOffPlatformAccessPa type: FlowOperationType.CHANGE_STATUS, request: { status: FlowStatus.DISABLED }, }, - }) + })) + if (isNil(error)) { + continue + } + log.warn({ + error, + flow: { id: flow.id }, + project: { id: flow.projectId }, + platform: { id: platformId }, + }, '[stopPlatformExecution] Trigger disable failed; forcing trigger-source removal so no new webhooks admit runs') + const { error: fallbackError } = await tryCatch(async () => triggerSourceService(log).disable({ + flowId: flow.id, + projectId: flow.projectId, + simulate: false, + ignoreError: true, + })) + if (!isNil(fallbackError)) { + log.warn({ + error: fallbackError, + flow: { id: flow.id }, + project: { id: flow.projectId }, + platform: { id: platformId }, + }, '[stopPlatformExecution] Fallback trigger-source disable also failed; teardown will continue and drainFlows will hard-delete the flow row anyway') + } + await flowRepo().update({ id: flow.id }, { status: FlowStatus.DISABLED }) + await flowExecutionCache(log).invalidate(flow.id) } await flowExecutionCache(log).invalidate(...flows.map((flow) => flow.id)) } @@ -153,7 +179,7 @@ type DrainFlowsParams = { log: FastifyBaseLogger } -type CutOffPlatformAccessParams = { +type BeginPlatformTeardownParams = { platformId: string log: FastifyBaseLogger } diff --git a/packages/server/api/src/app/platform/platform.controller.ts b/packages/server/api/src/app/platform/platform.controller.ts index 8c4cd68b023b..1a1d23fd4759 100644 --- a/packages/server/api/src/app/platform/platform.controller.ts +++ b/packages/server/api/src/app/platform/platform.controller.ts @@ -9,7 +9,7 @@ import { chatVisibilityHelper } from '../ee/agent/chat-visibility-helper' import { platformToEditMustBeOwnedByCurrentUser } from '../ee/authentication/ee-authorization' import { emailService } from '../ee/helper/email/email-service' import { platformPlanService } from '../ee/platform/platform-plan/platform-plan.service' -import { cutOffPlatformAccess } from '../ee/platform/platform-teardown-jobs' +import { beginPlatformTeardown } from '../ee/platform/platform-teardown-jobs' import { fileService } from '../file/file.service' import { attachMultipartFieldsToBody } from '../helper/multipart-body' import { system } from '../helper/system/system' @@ -168,7 +168,7 @@ export const platformController: FastifyPluginAsyncZod = async (app) => { }, }) - await cutOffPlatformAccess({ platformId, log: req.log }) + await beginPlatformTeardown({ platformId, log: req.log }) const { error: emailError } = await tryCatch(() => emailService(req.log).sendPlatformDeleted({ platformId,