From 958c1721739bbff6dda63ab8833e34d1beb47fbe Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Tue, 29 Aug 2023 21:23:15 +0200 Subject: [PATCH] fix premium info computation --- backend/windmill-api/src/workspaces.rs | 2 +- backend/windmill-worker/src/common.rs | 2 +- .../(logged)/workspace_settings/+page.svelte | 233 +----------------- 3 files changed, 7 insertions(+), 230 deletions(-) diff --git a/backend/windmill-api/src/workspaces.rs b/backend/windmill-api/src/workspaces.rs index 53a9fc59cd..c40fe0f9f6 100644 --- a/backend/windmill-api/src/workspaces.rs +++ b/backend/windmill-api/src/workspaces.rs @@ -252,7 +252,7 @@ async fn premium_info( require_admin(authed.is_admin, &authed.username)?; let mut tx = db.begin().await?; let row = sqlx::query_as::<_, PremiumWorkspaceInfo>( - "SELECT premium, usage.usage FROM workspace LEFT JOIN usage ON workspace.id = $1 AND usage.is_workspace IS true WHERE workspace.id = $1", + "SELECT premium, usage.usage FROM workspace LEFT JOIN usage ON usage.id = $1 AND usage.is_workspace IS true WHERE workspace.id = $1", ) .bind(w_id) .fetch_one(&mut *tx) diff --git a/backend/windmill-worker/src/common.rs b/backend/windmill-worker/src/common.rs index 29498b7673..4b33a10f98 100644 --- a/backend/windmill-worker/src/common.rs +++ b/backend/windmill-worker/src/common.rs @@ -295,7 +295,7 @@ pub async fn handle_child( .expect("update worker ping"); } let mem_peak = get_mem_peak(pid, nsjail).await; - tracing::info!("{job_id} still running. mem peak: {}kB", mem_peak); + tracing::info!("{job_id} in {} still running. mem peak: {}kB", _w_id, mem_peak); let mem_peak = if mem_peak > 0 { Some(mem_peak) } else { None }; if sqlx::query_scalar!("UPDATE queue SET mem_peak = GREATEST($1, mem_peak), last_ping = now() WHERE id = $2 RETURNING canceled", mem_peak, job_id) .fetch_optional(&db) diff --git a/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte b/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte index e5f58f67b6..684528f07b 100644 --- a/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte @@ -13,7 +13,6 @@ import Tooltip from '$lib/components/Tooltip.svelte' import WorkspaceUserSettings from '$lib/components/settings/WorkspaceUserSettings.svelte' import { WORKSPACE_SHOW_SLACK_CMD, WORKSPACE_SHOW_WEBHOOK_CLI_SYNC } from '$lib/consts' - import type { User } from '$lib/gen' import { OauthService, Script, WorkspaceService } from '$lib/gen' import { enterpriseLicense, @@ -24,19 +23,17 @@ workspaceStore } from '$lib/stores' import { sendUserToast } from '$lib/toast' - import { capitalize, setQueryWithoutLoad } from '$lib/utils' + import { setQueryWithoutLoad } from '$lib/utils' import { faSlack } from '@fortawesome/free-brands-svg-icons' - import { faBarsStaggered, faExternalLink, faScroll } from '@fortawesome/free-solid-svg-icons' + import { faBarsStaggered, faScroll } from '@fortawesome/free-solid-svg-icons' import { Slack } from 'lucide-svelte' - import DataTable from '$lib/components/table/DataTable.svelte' - import Cell from '$lib/components/table/Cell.svelte' - let users: User[] | undefined = undefined + import PremiumInfo from '$lib/components/settings/PremiumInfo.svelte' + let initialPath: string let scriptPath: string let team_name: string | undefined let itemKind: 'flow' | 'script' = 'flow' - let premium_info: { premium: boolean; usage?: number } | undefined = undefined let plan: string | undefined = undefined let customer_id: string | undefined = undefined let webhook: string | undefined = undefined @@ -152,16 +149,9 @@ errorHandlerInitialPath = errorHandlerScriptPath } - async function loadPremiumInfo() { - if (isCloudHosted()) { - premium_info = await WorkspaceService.getPremiumInfo({ workspace: $workspaceStore! }) - } - } - $: { if ($workspaceStore) { loadSettings() - loadPremiumInfo() } } @@ -181,27 +171,6 @@ sendUserToast(`workspace error handler removed`) } } - - const plans = { - Free: [ - 'Users use their individual global free-tier quotas when doing executions in this workspace', - '1 000 free global executions per-user per month' - ], - Team: [ - `$10/mo per seat`, - `Every seat includes 10 000 executions`, - `Every seat includes either 1 user OR 2 operators` - ], - Enterprise: [ - `Dedicated and isolated database and workers available (EU/US/Asia)`, - `Dedicated entire cluster available for (EU/US/Asia)`, - `SAML support with group syncing`, - `SLA`, - `Priority Support 24/7 with 3h response time and automation engineer assistance`, - `Design partners for Roadmap`, - `
Self-hosted licenses also available
` - ] - } @@ -267,199 +236,7 @@ > {/if} {:else if tab == 'premium'} - {#if isCloudHosted()} -
-
-
Plans
-
- {#if customer_id} -
- -

- See invoices, change billing information or subscription details -

-
- {/if} - -
- {#if premium_info?.premium} -
- {#if plan} -
- Current plan: {capitalize(plan ?? 'free')} plan -
- {:else} -
Current plan: Free plan
- {/if} - - {#if plan} - {@const team_factor = plan == 'team' ? 10 : 40} - {@const user_nb = users?.filter((x) => !x.operator)?.length ?? 0} - {@const operator_nb = users?.filter((x) => x.operator)?.length ?? 0} - {@const seats_from_users = Math.ceil(user_nb + operator_nb / 2)} - {@const seats_from_comps = Math.ceil((premium_info?.usage ?? 0) / 10000)} - -
- - - - - Authors - - Actual pricing is calculated on the MAXIMUM number of users in a given - billing period, see the customer portal for more info. - - - -
- {user_nb} -
-
- - - - Operators - - Actual pricing is calculated on the MAXIMUM number of operators in a - given billing period, see the customer portal for more info. - - - -
- {operator_nb} -
-
- - - Seats from authors + operators - -
- ceil({user_nb} + {operator_nb}/2) = {seats_from_users} -
-
- - - Computations executed this month - -
- {premium_info?.usage ?? 0} -
-
- - - Seats from computations - -
- ceil({premium_info?.usage ?? 0} / 10 000) = {seats_from_comps} -
-
- - - Total seats - -
- max({seats_from_comps}, {seats_from_users}) * {team_factor} = ${Math.max( - seats_from_comps, - seats_from_users - ) * team_factor}/mo -
-
- - -
-
- {/if} -
- {:else} - This workspace is NOT on a team plan. Users use their global free-tier quotas when - doing executions in this workspace. Upgrade to a Team or Enterprise plan to unlock unlimited - executions in this workspace. - {/if} -
- -
All plans
- -
- {#each Object.entries(plans) as [planTitle, planDesc]} -
-

{planTitle}

-
    - {#each planDesc as item} -
  • {@html item}
  • - {/each} -
- -
- {#if planTitle == 'Team'} - {#if plan != 'team'} -
- -
- {:else} -
Workspace is on the team plan
- {/if} - {:else if planTitle == 'Enterprise'} - {#if plan != 'enterprise'} -
- -
- {:else} -
Workspace is on enterprise plan
- {/if} - {:else if !plan} - Workspace is on the free plan - {:else} -
- -
- {/if} -
- {/each} -
-
-
Frequently asked questions
- -
-
-
What is an execution?
-
- The single credit-unit is called an "execution". An execution corresponds to a - single job whose duration is less than 1s. For any additional seconds of - computation, an additional execution is accounted for. Jobs are executed on one - powerful virtual CPU with 2Gb of memory. Most jobs will take less than 200ms to - execute. -
-
-
-
- What is the difference between an author and an operator? -
-
- An author can write scripts/flows/apps/variables/resources. An operator can only - run/view them. -
-
-
-
- {/if} + {:else if tab == 'slack'}