diff --git a/airbyte-webapp/src/components/connection/ConnectionStatus/useConnectionStatus.test.ts b/airbyte-webapp/src/components/connection/ConnectionStatus/useConnectionStatus.test.ts index 6e10bd087b2..bcca2e827c4 100644 --- a/airbyte-webapp/src/components/connection/ConnectionStatus/useConnectionStatus.test.ts +++ b/airbyte-webapp/src/components/connection/ConnectionStatus/useConnectionStatus.test.ts @@ -255,26 +255,31 @@ describe("isHandleableScheduledConnection", () => { }); describe("useConnectionStatus", () => { - /* Cases currently failing: - ${"most recent sync was successful, breaking schema changes"} | ${ConnectionStatusIndicatorStatus.ActionRequired} | ${ConnectionStatus.inactive} | ${SchemaChange.breaking} | ${ConnectionSyncStatus.ACTIVE} | ${dayjs().subtract(1, "minute").unix()} | ${undefined} | ${undefined} - ${"breaking schema changes, sync is outside of 2x frequency"} | ${ConnectionStatusIndicatorStatus.ActionRequired} | ${ConnectionStatus.inactive} | ${SchemaChange.breaking} | ${ConnectionSyncStatus.FAILED} | ${dayjs().subtract(50, "hours").unix()} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} - ${"last sync was cancelled, but last successful sync is within 2x frequency"} | ${ConnectionStatusIndicatorStatus.Late} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.CANCELLED} | ${dayjs().subtract(50, "hours").unix()} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} - */ + const within1xFrequency = dayjs().subtract(20, "hours").unix(); + const within2xFrequency = dayjs().subtract(28, "hours").unix(); + const outside2xFrequency = dayjs().subtract(50, "hours").unix(); it.each` - title | expectedConnectionStatus | connectionStatus | schemaChange | connectionSyncStatus | lastSuccessfulSync | scheduleType | scheduleData - ${"most recent sync was successful, no schema changes"} | ${ConnectionStatusIndicatorStatus.OnTime} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.ACTIVE} | ${dayjs().subtract(1, "minute").unix()} | ${undefined} | ${undefined} - ${"new connection, not scheduled"} | ${ConnectionStatusIndicatorStatus.Pending} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.EMPTY} | ${undefined} | ${undefined} | ${undefined} - ${"new connection, scheduled"} | ${ConnectionStatusIndicatorStatus.Pending} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.EMPTY} | ${undefined} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} - ${"connection status is failed, no previous success"} | ${ConnectionStatusIndicatorStatus.Error} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.FAILED} | ${undefined} | ${undefined} | ${undefined} - ${"connection status is failed, no previous success"} | ${ConnectionStatusIndicatorStatus.OnTrack} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.FAILED} | ${dayjs().subtract(26, "hours").unix()} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} - ${"connection status is failed, last previous success was within 2x schedule frequency"} | ${ConnectionStatusIndicatorStatus.Error} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.FAILED} | ${dayjs().subtract(5, "minutes").unix()} | ${"cron"} | ${{ cronExpression: "* * * * *", cronTimeZone: "UTC" }} - ${"connection status is failed, last previous success was a while ago, but cron is never late"} | ${ConnectionStatusIndicatorStatus.Error} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.FAILED} | ${dayjs().subtract(50, "hours").unix()} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} - ${"connection status is failed, last previous success was outside 2x schedule frequency"} | ${ConnectionStatusIndicatorStatus.OnTrack} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.ACTIVE} | ${dayjs().subtract(28, "hours").unix()} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} - ${"last sync was successful, but the next sync hasn't started (within 2x frequency)"} | ${ConnectionStatusIndicatorStatus.Late} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.ACTIVE} | ${dayjs().subtract(52, "hours").unix()} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} - ${"last sync was successful, but the next sync hasn't started (outside 2x frequency)"} | ${ConnectionStatusIndicatorStatus.OnTime} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.ACTIVE} | ${dayjs().subtract(52, "hours").unix()} | ${"cron"} | ${{ cronExpression: "* * * * *", cronTimeZone: "UTC" }} - ${"last sync was successful, but the next cron-scheduled sync hasn't started (cron is never late)"} | ${ConnectionStatusIndicatorStatus.Cancelled} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.CANCELLED} | ${dayjs().subtract(2, "hours").unix()} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} - ${"last sync was cancelled, but last successful sync is within 1x frequency"} | ${ConnectionStatusIndicatorStatus.Cancelled} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.CANCELLED} | ${dayjs().subtract(2, "hours").unix()} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} + title | expectedConnectionStatus | connectionStatus | schemaChange | connectionSyncStatus | lastSuccessfulSync | scheduleType | scheduleData + ${"most recent sync was successful, no schema changes"} | ${ConnectionStatusIndicatorStatus.OnTime} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.ACTIVE} | ${within1xFrequency} | ${undefined} | ${undefined} + ${"most recent sync was successful, breaking schema changes"} | ${ConnectionStatusIndicatorStatus.ActionRequired} | ${ConnectionStatus.inactive} | ${SchemaChange.breaking} | ${ConnectionSyncStatus.ACTIVE} | ${within1xFrequency} | ${undefined} | ${undefined} + ${"breaking schema changes, sync is within 1x frequency"} | ${ConnectionStatusIndicatorStatus.ActionRequired} | ${ConnectionStatus.inactive} | ${SchemaChange.breaking} | ${ConnectionSyncStatus.FAILED} | ${within1xFrequency} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} + ${"breaking schema changes, sync is within 2x frequency"} | ${ConnectionStatusIndicatorStatus.ActionRequired} | ${ConnectionStatus.inactive} | ${SchemaChange.breaking} | ${ConnectionSyncStatus.FAILED} | ${within2xFrequency} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} + ${"breaking schema changes, sync is outside of 2x frequency"} | ${ConnectionStatusIndicatorStatus.ActionRequired} | ${ConnectionStatus.inactive} | ${SchemaChange.breaking} | ${ConnectionSyncStatus.FAILED} | ${outside2xFrequency} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} + ${"new connection, not scheduled"} | ${ConnectionStatusIndicatorStatus.Pending} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.EMPTY} | ${undefined} | ${undefined} | ${undefined} + ${"new connection, scheduled"} | ${ConnectionStatusIndicatorStatus.Pending} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.EMPTY} | ${undefined} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} + ${"connection status is failed, no previous success"} | ${ConnectionStatusIndicatorStatus.Error} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.FAILED} | ${undefined} | ${undefined} | ${undefined} + ${"connection status is failed, last previous success was within 1x schedule frequency"} | ${ConnectionStatusIndicatorStatus.OnTrack} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.FAILED} | ${within1xFrequency} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} + ${"connection status is failed, last previous success was within 2x schedule frequency"} | ${ConnectionStatusIndicatorStatus.OnTrack} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.FAILED} | ${within2xFrequency} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} + ${"connection status is failed, last previous success was within 2x schedule frequency (cron)"} | ${ConnectionStatusIndicatorStatus.Error} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.FAILED} | ${within2xFrequency} | ${"cron"} | ${{ cronExpression: "* * * * *", cronTimeZone: "UTC" }} + ${"connection status is failed, last previous success was outside 2x schedule frequency"} | ${ConnectionStatusIndicatorStatus.Error} | ${ConnectionStatus.active} | ${SchemaChange.no_change} | ${ConnectionSyncStatus.FAILED} | ${outside2xFrequency} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} + ${"connection status is failed, last previous success was within 2x schedule frequency"} | ${ConnectionStatusIndicatorStatus.OnTrack} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.ACTIVE} | ${within2xFrequency} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} + ${"last sync was successful, but the next sync hasn't started (outside 2x frequency)"} | ${ConnectionStatusIndicatorStatus.Late} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.ACTIVE} | ${outside2xFrequency} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} + ${"last sync was successful, but the next sync hasn't started (outside 2x frequency, cron)"} | ${ConnectionStatusIndicatorStatus.OnTime} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.ACTIVE} | ${outside2xFrequency} | ${"cron"} | ${{ cronExpression: "* * * * *", cronTimeZone: "UTC" }} + ${"last sync was cancelled, but the next cron-scheduled sync hasn't started"} | ${ConnectionStatusIndicatorStatus.OnTime} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.CANCELLED} | ${within1xFrequency} | ${"cron"} | ${{ cronExpression: "* * * * *", cronTimeZone: "UTC" }} + ${"last sync was cancelled, but last successful sync is within 1x frequency"} | ${ConnectionStatusIndicatorStatus.OnTime} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.CANCELLED} | ${within1xFrequency} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} + ${"last sync was cancelled, but last successful sync is within 2x frequency"} | ${ConnectionStatusIndicatorStatus.OnTrack} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.CANCELLED} | ${within2xFrequency} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} + ${"last sync was cancelled, but last successful sync is outside 2x frequency"} | ${ConnectionStatusIndicatorStatus.Late} | ${ConnectionStatus.active} | ${SchemaChange.non_breaking} | ${ConnectionSyncStatus.CANCELLED} | ${outside2xFrequency} | ${"basic"} | ${{ units: 24, timeUnit: "hours" }} `( "$title:" + "\n\treturns $expectedConnectionStatus when" + diff --git a/airbyte-webapp/src/components/connection/ConnectionStatus/useConnectionStatus.ts b/airbyte-webapp/src/components/connection/ConnectionStatus/useConnectionStatus.ts index 599694859b2..bc4070634ae 100644 --- a/airbyte-webapp/src/components/connection/ConnectionStatus/useConnectionStatus.ts +++ b/airbyte-webapp/src/components/connection/ConnectionStatus/useConnectionStatus.ts @@ -48,12 +48,15 @@ export const useConnectionStatus = () => { const lateMultiplier = useLateMultiplierExperiment(); const errorMultiplier = useErrorMultiplierExperiment(); - // Disabling the schema changes as it's the only actionable error and is per-connection, not stream const { connection } = useConnectionEditService(); const { hasBreakingSchemaChange } = useSchemaChanges(connection.schemaChange); const { connectionEnabled, connectionStatus, lastSuccessfulSync } = useConnectionSyncContext(); + if (hasBreakingSchemaChange) { + return ConnectionStatusIndicatorStatus.ActionRequired; + } + if (!connectionEnabled) { return ConnectionStatusIndicatorStatus.Disabled; } @@ -73,14 +76,6 @@ export const useConnectionStatus = () => { return ConnectionStatusIndicatorStatus.Error; } - if (hasBreakingSchemaChange && isConnectionLate(connection, lastSuccessfulSync, lateMultiplier)) { - return ConnectionStatusIndicatorStatus.ActionRequired; - } - - if (connectionStatus === ConnectionSyncStatus.CANCELLED) { - return ConnectionStatusIndicatorStatus.Cancelled; - } - // The `late` value is based on the `connection.streamCentricUI.late` experiment if (isConnectionLate(connection, lastSuccessfulSync, lateMultiplier)) { return ConnectionStatusIndicatorStatus.Late; diff --git a/airbyte-webapp/src/components/connection/ConnectionStatusIndicator/ConnectionStatusIndicator.tsx b/airbyte-webapp/src/components/connection/ConnectionStatusIndicator/ConnectionStatusIndicator.tsx index d48da97f3b0..73a5aa5216c 100644 --- a/airbyte-webapp/src/components/connection/ConnectionStatusIndicator/ConnectionStatusIndicator.tsx +++ b/airbyte-webapp/src/components/connection/ConnectionStatusIndicator/ConnectionStatusIndicator.tsx @@ -16,7 +16,6 @@ export enum ConnectionStatusIndicatorStatus { Error = "error", ActionRequired = "actionRequired", Disabled = "disabled", - Cancelled = "cancelled", } const ICON_BY_STATUS: Readonly> = { @@ -27,7 +26,6 @@ const ICON_BY_STATUS: Readonly, late: , actionRequired: , - cancelled: , }; const STYLE_BY_STATUS: Readonly> = { @@ -38,7 +36,6 @@ const STYLE_BY_STATUS: Readonly> pending: styles["status--pending"], late: styles["status--late"], actionRequired: styles["status--actionRequired"], - cancelled: styles["status--cancelled"], }; const BOX_STYLE_BY_STATUS: Readonly> = { @@ -49,7 +46,6 @@ const BOX_STYLE_BY_STATUS: Readonly { const { connection } = useConnectionEditService(); const [activeJob, setActiveJob] = useState(jobs[0]?.job); diff --git a/airbyte-webapp/src/pages/connections/StreamStatusPage/ConnectionStatusOverview.tsx b/airbyte-webapp/src/pages/connections/StreamStatusPage/ConnectionStatusOverview.tsx index 89e7b5b59c4..fac97d44f48 100644 --- a/airbyte-webapp/src/pages/connections/StreamStatusPage/ConnectionStatusOverview.tsx +++ b/airbyte-webapp/src/pages/connections/StreamStatusPage/ConnectionStatusOverview.tsx @@ -23,7 +23,6 @@ const MESSAGE_BY_STATUS: Readonly {