feat: add LANGFLOW_AUTO_SAVING_INTERVAL .env variable for flow auto-saving debounce (#3478)

* 📝 (langflow): Add support for configuring auto saving interval for Langflow
📝 (langflow): Update ConfigResponse and Settings to include auto_saving_interval
📝 (frontend): Update useGetConfigQuery and useSaveConfig to handle auto_saving_interval
📝 (frontend): Update useAutoSaveFlow and flowsManagerStore to handle auto saving interval

* 📝 (util.py): add support for setting auto_saving_interval in update_settings function to allow customization of auto-saving interval
This commit is contained in:
Cristhian Zanforlin Lousa 2024-08-21 16:02:26 -03:00 • committed by GitHub
commit 1db1e3af3d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 28 additions and 2 deletions

View file

@ -125,6 +125,11 @@ def run(
help="Defines if the auto save is enabled.", help="Defines if the auto save is enabled.",
envvar="LANGFLOW_AUTO_SAVING", envvar="LANGFLOW_AUTO_SAVING",
), ),
auto_saving_interval: bool = typer.Option(
True,
help="Defines the debounce time for the auto save.",
envvar="LANGFLOW_AUTO_SAVING_INTERVAL",
),
): ):
""" """
Run Langflow. Run Langflow.
@ -143,6 +148,7 @@ def run(
components_path=components_path, components_path=components_path,
store=store, store=store,
auto_saving=auto_saving, auto_saving=auto_saving,
auto_saving_interval=auto_saving_interval,
) )
# create path object if path is provided # create path object if path is provided
static_files_dir: Optional[Path] = Path(path) if path else None static_files_dir: Optional[Path] = Path(path) if path else None

View file

@ -331,3 +331,4 @@ class FlowDataRequest(BaseModel):
class ConfigResponse(BaseModel): class ConfigResponse(BaseModel):
frontend_timeout: int frontend_timeout: int
auto_saving: bool auto_saving: bool
auto_saving_interval: int

View file

@ -157,6 +157,8 @@ class Settings(BaseSettings):
# Config # Config
auto_saving: bool = True auto_saving: bool = True
"""If set to True, Langflow will auto save flows.""" """If set to True, Langflow will auto save flows."""
auto_saving_interval: int = 300
"""The interval in ms at which Langflow will auto save flows."""
@field_validator("dev") @field_validator("dev")
@classmethod @classmethod

View file

@ -429,6 +429,7 @@ def update_settings(
components_path: Optional[Path] = None, components_path: Optional[Path] = None,
store: bool = True, store: bool = True,
auto_saving: bool = True, auto_saving: bool = True,
auto_saving_interval: int = 300,
): ):
"""Update the settings from a config file.""" """Update the settings from a config file."""
from langflow.services.utils import initialize_settings_service from langflow.services.utils import initialize_settings_service
@ -455,6 +456,9 @@ def update_settings(
if not auto_saving: if not auto_saving:
logger.debug("Setting auto_saving to False") logger.debug("Setting auto_saving to False")
settings_service.settings.update_settings(auto_saving=False) settings_service.settings.update_settings(auto_saving=False)
if auto_saving_interval:
logger.debug(f"Setting auto_saving_interval to {auto_saving_interval}")
settings_service.settings.update_settings(auto_saving_interval=auto_saving_interval)
def is_class_method(func, cls): def is_class_method(func, cls):

View file

@ -6,6 +6,7 @@ import { UseRequestProcessor } from "../../services/request-processor";
export interface ConfigResponse { export interface ConfigResponse {
frontend_timeout: number; frontend_timeout: number;
auto_saving: boolean; auto_saving: boolean;
auto_saving_interval: number;
} }
export const useGetConfigQuery: useQueryFunctionType< export const useGetConfigQuery: useQueryFunctionType<

View file

@ -1,4 +1,3 @@
import { SAVE_DEBOUNCE_TIME } from "@/constants/constants";
import useFlowsManagerStore from "@/stores/flowsManagerStore"; import useFlowsManagerStore from "@/stores/flowsManagerStore";
import { FlowType } from "@/types/flow"; import { FlowType } from "@/types/flow";
import { useDebounce } from "../use-debounce"; import { useDebounce } from "../use-debounce";
@ -7,12 +6,15 @@ import useSaveFlow from "./use-save-flow";
const useAutoSaveFlow = () => { const useAutoSaveFlow = () => {
const saveFlow = useSaveFlow(); const saveFlow = useSaveFlow();
const autoSaving = useFlowsManagerStore((state) => state.autoSaving); const autoSaving = useFlowsManagerStore((state) => state.autoSaving);
const autoSavingInterval = useFlowsManagerStore(
(state) => state.autoSavingInterval,
);
const autoSaveFlow = useDebounce((flow?: FlowType) => { const autoSaveFlow = useDebounce((flow?: FlowType) => {
if (autoSaving) { if (autoSaving) {
saveFlow(flow); saveFlow(flow);
} }
}, SAVE_DEBOUNCE_TIME); }, autoSavingInterval);
return autoSaveFlow; return autoSaveFlow;
}; };

View file

@ -6,6 +6,9 @@ import { useGetConfigQuery } from "../controllers/API/queries/config/use-get-con
function useSaveConfig() { function useSaveConfig() {
const { data } = useGetConfigQuery(); const { data } = useGetConfigQuery();
const setAutoSaving = useFlowsManagerStore((state) => state.setAutoSaving); const setAutoSaving = useFlowsManagerStore((state) => state.setAutoSaving);
const setAutoSavingInterval = useFlowsManagerStore(
(state) => state.setAutoSavingInterval,
);
useEffect(() => { useEffect(() => {
if (data) { if (data) {
@ -15,6 +18,7 @@ function useSaveConfig() {
axios.defaults.baseURL = ""; axios.defaults.baseURL = "";
axios.defaults.timeout = timeoutInMilliseconds; axios.defaults.timeout = timeoutInMilliseconds;
setAutoSaving(data.auto_saving); setAutoSaving(data.auto_saving);
setAutoSavingInterval(data.auto_saving_interval);
} }
}, [data]); }, [data]);
} }

View file

@ -1,3 +1,4 @@
import { SAVE_DEBOUNCE_TIME } from "@/constants/constants";
import { cloneDeep } from "lodash"; import { cloneDeep } from "lodash";
import { create } from "zustand"; import { create } from "zustand";
import { FlowType } from "../types/flow"; import { FlowType } from "../types/flow";
@ -18,6 +19,9 @@ const future = {};
const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
autoSaving: true, autoSaving: true,
setAutoSaving: (autoSaving: boolean) => set({ autoSaving }), setAutoSaving: (autoSaving: boolean) => set({ autoSaving }),
autoSavingInterval: SAVE_DEBOUNCE_TIME,
setAutoSavingInterval: (autoSavingInterval: number) =>
set({ autoSavingInterval }),
examples: [], examples: [],
setExamples: (examples: FlowType[]) => { setExamples: (examples: FlowType[]) => {
set({ examples }); set({ examples });

View file

@ -22,6 +22,8 @@ export type FlowsManagerStoreType = {
searchFlowsComponents: string; searchFlowsComponents: string;
selectedFlowsComponentsCards: string[]; selectedFlowsComponentsCards: string[];
setSelectedFlowsComponentsCards: (selected: string[]) => void; setSelectedFlowsComponentsCards: (selected: string[]) => void;
autoSavingInterval: number;
setAutoSavingInterval: (autoSavingInterval: number) => void;
}; };
export type UseUndoRedoOptions = { export type UseUndoRedoOptions = {