Feat: Runtime options (#898)

* feat(runtime-options): add runtime options, update rowy run github link

* Update src/components/TableModals/ExtensionsModal/ExtensionList.tsx

* Update src/components/TableModals/ExtensionsModal/RuntimeOptions.tsx
This commit is contained in:
Han Tuerker
2022-10-27 10:09:00 +03:00
committed by GitHub
parent 881dba0311
commit e4da6bcb06
5 changed files with 188 additions and 22 deletions

View File

@@ -23,7 +23,6 @@ import {
} from "@src/atoms/tableScope";
import { useSnackLogContext } from "@src/contexts/SnackLogContext";
import { emptyExtensionObject, IExtension, ExtensionType } from "./utils";
import { runRoutes } from "@src/constants/runRoutes";
import { analytics, logEvent } from "@src/analytics";
import {
@@ -31,6 +30,14 @@ import {
getTableBuildFunctionPathname,
} from "@src/utils/table";
import {
emptyExtensionObject,
IExtension,
ExtensionType,
IRuntimeOptions,
} from "./utils";
import RuntimeOptions from "./RuntimeOptions";
export default function ExtensionsModal({ onClose }: ITableModalProps) {
const [currentUser] = useAtom(currentUserAtom, projectScope);
const [rowyRun] = useAtom(rowyRunAtom, projectScope);
@@ -39,12 +46,24 @@ export default function ExtensionsModal({ onClose }: ITableModalProps) {
const [tableSchema] = useAtom(tableSchemaAtom, tableScope);
const [updateTableSchema] = useAtom(updateTableSchemaAtom, tableScope);
const currentExtensionObjects = (tableSchema.extensionObjects ??
[]) as IExtension[];
const [localExtensionsObjects, setLocalExtensionsObjects] = useState(
currentExtensionObjects
tableSchema.extensionObjects ?? []
);
const [localRuntimeOptions, setLocalRuntimeOptions] = useState(
tableSchema.runtimeOptions ?? {}
);
const errors = {
runtimeOptions: {
timeoutSeconds: !(
!!localRuntimeOptions.timeoutSeconds &&
localRuntimeOptions.timeoutSeconds > 0 &&
localRuntimeOptions.timeoutSeconds <= 540
),
},
};
const [openMigrationGuide, setOpenMigrationGuide] = useState(false);
useEffect(() => {
if (tableSchema.sparks) setOpenMigrationGuide(true);
@@ -57,7 +76,9 @@ export default function ExtensionsModal({ onClose }: ITableModalProps) {
} | null>(null);
const snackLogContext = useSnackLogContext();
const edited = !isEqual(currentExtensionObjects, localExtensionsObjects);
const edited =
!isEqual(tableSchema.extensionObjects ?? [], localExtensionsObjects) ||
!isEqual(tableSchema.runtimeOptions ?? {}, localRuntimeOptions);
const handleClose = (
_setOpen: React.Dispatch<React.SetStateAction<boolean>>
@@ -70,7 +91,8 @@ export default function ExtensionsModal({ onClose }: ITableModalProps) {
cancel: "Keep",
handleConfirm: () => {
_setOpen(false);
setLocalExtensionsObjects(currentExtensionObjects);
setLocalExtensionsObjects(tableSchema.extensionObjects ?? []);
setLocalRuntimeOptions(tableSchema.runtimeOptions ?? {});
onClose();
},
});
@@ -79,15 +101,18 @@ export default function ExtensionsModal({ onClose }: ITableModalProps) {
}
};
const handleSaveExtensions = async (callback?: Function) => {
const handleSave = async (callback?: Function) => {
if (updateTableSchema)
await updateTableSchema({ extensionObjects: localExtensionsObjects });
await updateTableSchema({
extensionObjects: localExtensionsObjects,
runtimeOptions: localRuntimeOptions,
});
if (callback) callback();
onClose();
};
const handleSaveDeploy = async () => {
handleSaveExtensions(() => {
handleSave(() => {
try {
snackLogContext.requestSnackLog();
rowyRun({
@@ -132,6 +157,13 @@ export default function ExtensionsModal({ onClose }: ITableModalProps) {
setExtensionModal(null);
};
const handleUpdateRuntimeOptions = (update: IRuntimeOptions) => {
setLocalRuntimeOptions((runtimeOptions) => ({
...runtimeOptions,
...update,
}));
};
const handleUpdateActive = (index: number, active: boolean) => {
setLocalExtensionsObjects(
localExtensionsObjects.map((extensionObject, i) => {
@@ -217,24 +249,31 @@ export default function ExtensionsModal({ onClose }: ITableModalProps) {
/>
}
children={
<ExtensionList
extensions={localExtensionsObjects}
handleUpdateActive={handleUpdateActive}
handleEdit={handleEdit}
handleDuplicate={handleDuplicate}
handleDelete={handleDelete}
/>
<>
<ExtensionList
extensions={localExtensionsObjects}
handleUpdateActive={handleUpdateActive}
handleEdit={handleEdit}
handleDuplicate={handleDuplicate}
handleDelete={handleDelete}
/>
<RuntimeOptions
runtimeOptions={localRuntimeOptions}
handleUpdate={handleUpdateRuntimeOptions}
errors={errors.runtimeOptions}
/>
</>
}
actions={{
primary: {
children: "Save & Deploy",
onClick: handleSaveDeploy,
disabled: !edited,
disabled: !edited || errors.runtimeOptions.timeoutSeconds,
},
secondary: {
children: "Save",
onClick: () => handleSaveExtensions(),
disabled: !edited,
onClick: () => handleSave(),
disabled: !edited || errors.runtimeOptions.timeoutSeconds,
},
}}
/>

View File

@@ -0,0 +1,117 @@
import { useState } from "react";
import { useAtom, useSetAtom } from "jotai";
import {
Accordion,
AccordionDetails,
AccordionSummary,
Button,
Grid,
InputAdornment,
TextField,
Typography,
} from "@mui/material";
import { ChevronDown } from "@src/assets/icons";
import MultiSelect from "@rowy/multiselect";
import {
compatibleRowyRunVersionAtom,
projectScope,
rowyRunModalAtom,
} from "@src/atoms/projectScope";
import { IRuntimeOptions } from "./utils";
export default function RuntimeOptions({
runtimeOptions,
handleUpdate,
errors,
}: {
runtimeOptions: IRuntimeOptions;
handleUpdate: (runtimeOptions: IRuntimeOptions) => void;
errors: { timeoutSeconds: boolean };
}) {
const [compatibleRowyRunVersion] = useAtom(
compatibleRowyRunVersionAtom,
projectScope
);
const openRowyRunModal = useSetAtom(rowyRunModalAtom, projectScope);
const [expanded, setExpanded] = useState(false);
const isCompatibleRowyRun = compatibleRowyRunVersion({ minVersion: "1.6.4" });
return (
<Accordion
sx={{
padding: 0,
boxShadow: "none",
backgroundImage: "inherit",
backgroundColor: "inherit",
}}
expanded={isCompatibleRowyRun && expanded}
>
<AccordionSummary
sx={{ padding: 0 }}
expandIcon={
isCompatibleRowyRun ? (
<ChevronDown />
) : (
<Button>Update Rowy Run</Button>
)
}
onClick={() =>
isCompatibleRowyRun
? setExpanded(!expanded)
: openRowyRunModal({
version: "1.6.4",
feature: "Runtime options",
})
}
>
<Typography variant="subtitle1">Runtime options</Typography>
</AccordionSummary>
<AccordionDetails sx={{ padding: 0 }}>
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
<MultiSelect
label="Memory Allocated"
value={runtimeOptions.memory ?? "256MB"}
onChange={(value) => handleUpdate({ memory: value ?? "256MB" })}
multiple={false}
options={["128MB", "256MB", "512MB", "1GB", "2GB", "4GB", "8GB"]}
/>
</Grid>
<Grid item xs={12} md={6}>
<TextField
value={runtimeOptions.timeoutSeconds ?? 60}
label="Timeout"
fullWidth
InputProps={{
endAdornment: (
<InputAdornment position="end">seconds</InputAdornment>
),
}}
onChange={(e) =>
!isNaN(Number(e.target.value)) &&
handleUpdate({
timeoutSeconds: Number(e.target.value),
})
}
inputProps={{
inputMode: "numeric",
}}
error={errors.timeoutSeconds}
helperText={
errors.timeoutSeconds
? "Timeout must be an integer between 1 and 540"
: "The maximum timeout that can be specified is 9 mins (540 seconds)"
}
/>
</Grid>
</Grid>
</AccordionDetails>
</Accordion>
);
}

View File

@@ -52,6 +52,12 @@ export interface IExtension {
trackedFields?: string[];
}
// https://firebase.google.com/docs/functions/manage-functions#set_runtime_options
export interface IRuntimeOptions {
memory?: "128MB" | "256MB" | "512MB" | "1GB" | "2GB" | "4GB" | "8GB";
timeoutSeconds?: number;
}
export const triggerTypes: ExtensionTrigger[] = ["create", "update", "delete"];
const extensionBodyTemplate = {

View File

@@ -15,8 +15,8 @@ export const EXTERNAL_LINKS = {
twitter: "https://twitter.com/rowyio",
productHunt: "https://www.producthunt.com/products/rowy-2",
rowyRun: meta.repository.url.replace(".git", "Run"),
rowyRunGitHub: meta.repository.url.replace(".git", "Run"),
rowyRun: meta.repository.url.replace("rowy.git", "backend"),
rowyRunGitHub: meta.repository.url.replace("rowy.git", "backend"),
// prettier-ignore
rowyRunDeploy: `https://deploy.cloud.run/?git_repo=${meta.repository.url.replace(".git", "Run")}.git`,

View File

@@ -4,7 +4,10 @@ import type {
DocumentData,
DocumentReference,
} from "firebase/firestore";
import { IExtension } from "@src/components/TableModals/ExtensionsModal/utils";
import {
IExtension,
IRuntimeOptions,
} from "@src/components/TableModals/ExtensionsModal/utils";
import { IWebhook } from "@src/components/TableModals/WebhooksModal/utils";
/**
@@ -104,6 +107,7 @@ export type TableSchema = {
extensionObjects?: IExtension[];
compiledExtension?: string;
webhooks?: IWebhook[];
runtimeOptions?: IRuntimeOptions;
/** @deprecated Migrate to Extensions */
sparks?: string;