📝 (endpoints.py): Add support for caching components to improve performance and reduce load on the server
📝 (setup.py): Change function create_or_update_starter_projects to be asynchronous to handle await calls 📝 (types.py): Add caching mechanism to function aget_all_components to improve performance and reduce redundant calls 📝 (main.py): Change call to create_or_update_starter_projects to be awaited to handle asynchronous operation 📝 (index.tsx): Add functionality to reload components in the menu bar to update component data dynamically 📝 (index.ts): Modify getAll function to accept a force_refresh parameter to force a refresh of data 📝 (typesStore.ts): Update getTypes function to accept a force_refresh parameter and pass it to the getAll function 📝 (index.ts): Update getTypes function in TypesStoreType to accept a force_refresh parameter 📝 (test_initial_setup.py): Update test_create_or_update_starter_projects to await the asynchronous function create_or_update_starter_projects
This commit is contained in:
parent
dd4b617b48
commit
a65965fcb3
9 changed files with 75 additions and 13 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
from asyncio import Lock
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
from typing import TYPE_CHECKING, Annotated, List, Optional, Union
|
from typing import TYPE_CHECKING, Annotated, List, Optional, Union
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
@ -32,11 +33,18 @@ from langflow.services.cache.utils import save_uploaded_file
|
||||||
from langflow.services.database.models.flow import Flow
|
from langflow.services.database.models.flow import Flow
|
||||||
from langflow.services.database.models.flow.utils import get_all_webhook_components_in_flow, get_flow_by_id
|
from langflow.services.database.models.flow.utils import get_all_webhook_components_in_flow, get_flow_by_id
|
||||||
from langflow.services.database.models.user.model import User
|
from langflow.services.database.models.user.model import User
|
||||||
from langflow.services.deps import get_session, get_session_service, get_settings_service, get_task_service
|
from langflow.services.deps import (
|
||||||
|
get_cache_service,
|
||||||
|
get_session,
|
||||||
|
get_session_service,
|
||||||
|
get_settings_service,
|
||||||
|
get_task_service,
|
||||||
|
)
|
||||||
from langflow.services.session.service import SessionService
|
from langflow.services.session.service import SessionService
|
||||||
from langflow.services.task.service import TaskService
|
from langflow.services.task.service import TaskService
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from langflow.services.cache.base import CacheService
|
||||||
from langflow.services.settings.manager import SettingsService
|
from langflow.services.settings.manager import SettingsService
|
||||||
|
|
||||||
router = APIRouter(tags=["Base"])
|
router = APIRouter(tags=["Base"])
|
||||||
|
|
@ -45,12 +53,18 @@ router = APIRouter(tags=["Base"])
|
||||||
@router.get("/all", dependencies=[Depends(get_current_active_user)])
|
@router.get("/all", dependencies=[Depends(get_current_active_user)])
|
||||||
async def get_all(
|
async def get_all(
|
||||||
settings_service=Depends(get_settings_service),
|
settings_service=Depends(get_settings_service),
|
||||||
|
cache_service: "CacheService" = Depends(dependency=get_cache_service),
|
||||||
|
force_refresh: bool = False,
|
||||||
):
|
):
|
||||||
from langflow.interface.types import aget_all_types_dict
|
from langflow.interface.types import aget_all_types_dict
|
||||||
|
|
||||||
logger.debug("Building langchain types dict")
|
logger.debug("Building langchain types dict")
|
||||||
try:
|
try:
|
||||||
|
async with Lock() as lock:
|
||||||
|
all_types_dict = await cache_service.get(key="all_types_dict", lock=lock)
|
||||||
|
if not all_types_dict or force_refresh:
|
||||||
all_types_dict = await aget_all_types_dict(settings_service.settings.components_path)
|
all_types_dict = await aget_all_types_dict(settings_service.settings.components_path)
|
||||||
|
await cache_service.set(key="all_types_dict", value=all_types_dict, lock=lock)
|
||||||
return all_types_dict
|
return all_types_dict
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.exception(exc)
|
logger.exception(exc)
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ from loguru import logger
|
||||||
from sqlmodel import select
|
from sqlmodel import select
|
||||||
|
|
||||||
from langflow.base.constants import FIELD_FORMAT_ATTRIBUTES, NODE_FORMAT_ATTRIBUTES
|
from langflow.base.constants import FIELD_FORMAT_ATTRIBUTES, NODE_FORMAT_ATTRIBUTES
|
||||||
from langflow.interface.types import get_all_components
|
from langflow.interface.types import aget_all_components
|
||||||
from langflow.services.auth.utils import create_super_user
|
from langflow.services.auth.utils import create_super_user
|
||||||
from langflow.services.database.models.flow.model import Flow, FlowCreate
|
from langflow.services.database.models.flow.model import Flow, FlowCreate
|
||||||
from langflow.services.database.models.folder.model import Folder, FolderCreate
|
from langflow.services.database.models.folder.model import Folder, FolderCreate
|
||||||
|
|
@ -364,10 +364,10 @@ def find_existing_flow(session, flow_id, flow_endpoint_name):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def create_or_update_starter_projects():
|
async def create_or_update_starter_projects():
|
||||||
components_paths = get_settings_service().settings.components_path
|
components_paths = get_settings_service().settings.components_path
|
||||||
try:
|
try:
|
||||||
all_types_dict = get_all_components(components_paths, as_dict=True)
|
all_types_dict = await aget_all_components(components_paths, as_dict=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Error loading components: {e}")
|
logger.exception(f"Error loading components: {e}")
|
||||||
raise e
|
raise e
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
import json
|
||||||
|
|
||||||
|
from cachetools import TTLCache, cached
|
||||||
|
|
||||||
from langflow.custom.utils import abuild_custom_components, build_custom_components
|
from langflow.custom.utils import abuild_custom_components, build_custom_components
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -13,6 +17,27 @@ def get_all_types_dict(components_paths):
|
||||||
return custom_components_from_file
|
return custom_components_from_file
|
||||||
|
|
||||||
|
|
||||||
|
# TypeError: unhashable type: 'list'
|
||||||
|
def key_func(*args, **kwargs):
|
||||||
|
# components_paths is a list of paths
|
||||||
|
return json.dumps(args) + json.dumps(kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@cached(cache=TTLCache(maxsize=1, ttl=15), key=key_func)
|
||||||
|
async def aget_all_components(components_paths, as_dict=False):
|
||||||
|
"""Get all components names combining native and custom components."""
|
||||||
|
all_types_dict = await aget_all_types_dict(components_paths)
|
||||||
|
components = {} if as_dict else []
|
||||||
|
for category in all_types_dict.values():
|
||||||
|
for component in category.values():
|
||||||
|
component["name"] = component["display_name"]
|
||||||
|
if as_dict:
|
||||||
|
components[component["name"]] = component
|
||||||
|
else:
|
||||||
|
components.append(component)
|
||||||
|
return components
|
||||||
|
|
||||||
|
|
||||||
def get_all_components(components_paths, as_dict=False):
|
def get_all_components(components_paths, as_dict=False):
|
||||||
"""Get all components names combining native and custom components."""
|
"""Get all components names combining native and custom components."""
|
||||||
all_types_dict = get_all_types_dict(components_paths)
|
all_types_dict = get_all_types_dict(components_paths)
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ def get_lifespan(fix_migration=False, socketio_server=None, version=None):
|
||||||
setup_llm_caching()
|
setup_llm_caching()
|
||||||
LangfuseInstance.update()
|
LangfuseInstance.update()
|
||||||
initialize_super_user_if_needed()
|
initialize_super_user_if_needed()
|
||||||
create_or_update_starter_projects()
|
await create_or_update_starter_projects()
|
||||||
load_flows_from_directory()
|
load_flows_from_directory()
|
||||||
yield
|
yield
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import FlowSettingsModal from "../../../../modals/flowSettingsModal";
|
||||||
import useAlertStore from "../../../../stores/alertStore";
|
import useAlertStore from "../../../../stores/alertStore";
|
||||||
import useFlowStore from "../../../../stores/flowStore";
|
import useFlowStore from "../../../../stores/flowStore";
|
||||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||||
|
import { useTypesStore } from "../../../../stores/typesStore";
|
||||||
import { cn } from "../../../../utils/utils";
|
import { cn } from "../../../../utils/utils";
|
||||||
import IconComponent from "../../../genericIconComponent";
|
import IconComponent from "../../../genericIconComponent";
|
||||||
import ShadTooltip from "../../../shadTooltipComponent";
|
import ShadTooltip from "../../../shadTooltipComponent";
|
||||||
|
|
@ -34,6 +35,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
|
||||||
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const isBuilding = useFlowStore((state) => state.isBuilding);
|
const isBuilding = useFlowStore((state) => state.isBuilding);
|
||||||
|
const getTypes = useTypesStore((state) => state.getTypes);
|
||||||
|
|
||||||
function handleAddFlow(duplicate?: boolean) {
|
function handleAddFlow(duplicate?: boolean) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -55,6 +57,12 @@ export const MenuBar = ({}: {}): JSX.Element => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleReloadComponents() {
|
||||||
|
getTypes(true).then(() => {
|
||||||
|
setSuccessData({ title: "Components reloaded successfully" });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function printByBuildStatus() {
|
function printByBuildStatus() {
|
||||||
if (isBuilding) {
|
if (isBuilding) {
|
||||||
return "Building...";
|
return "Building...";
|
||||||
|
|
@ -188,6 +196,18 @@ export const MenuBar = ({}: {}): JSX.Element => {
|
||||||
)}
|
)}
|
||||||
<span className="absolute right-2 top-[0.4em]">Y</span>
|
<span className="absolute right-2 top-[0.4em]">Y</span>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
handleReloadComponents();
|
||||||
|
}}
|
||||||
|
className="cursor-pointer"
|
||||||
|
>
|
||||||
|
<IconComponent
|
||||||
|
name="RefreshCcw"
|
||||||
|
className="header-menu-options"
|
||||||
|
/>
|
||||||
|
Reload Components
|
||||||
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
<FlowSettingsModal
|
<FlowSettingsModal
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,13 @@ import {
|
||||||
/**
|
/**
|
||||||
* Fetches all objects from the API endpoint.
|
* Fetches all objects from the API endpoint.
|
||||||
*
|
*
|
||||||
|
* @param {boolean} force_refresh - Whether to force a refresh of the data.
|
||||||
* @returns {Promise<AxiosResponse<APIObjectType>>} A promise that resolves to an AxiosResponse containing all the objects.
|
* @returns {Promise<AxiosResponse<APIObjectType>>} A promise that resolves to an AxiosResponse containing all the objects.
|
||||||
*/
|
*/
|
||||||
export async function getAll(): Promise<AxiosResponse<APIObjectType>> {
|
export async function getAll(
|
||||||
return await api.get(`${BASE_URL_API}all`);
|
force_refresh: boolean = true
|
||||||
|
): Promise<AxiosResponse<APIObjectType>> {
|
||||||
|
return await api.get(`${BASE_URL_API}all?force_refresh=${force_refresh}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const GITHUB_API_URL = "https://api.github.com";
|
const GITHUB_API_URL = "https://api.github.com";
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@ export const useTypesStore = create<TypesStoreType>((set, get) => ({
|
||||||
types: {},
|
types: {},
|
||||||
templates: {},
|
templates: {},
|
||||||
data: {},
|
data: {},
|
||||||
getTypes: () => {
|
getTypes: (force_refresh: boolean = false) => {
|
||||||
return new Promise<void>(async (resolve, reject) => {
|
return new Promise<void>(async (resolve, reject) => {
|
||||||
const setLoading = useFlowsManagerStore.getState().setIsLoading;
|
const setLoading = useFlowsManagerStore.getState().setIsLoading;
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
getAll()
|
getAll(force_refresh)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const data = response?.data;
|
const data = response?.data;
|
||||||
useAlertStore.setState({ loading: false });
|
useAlertStore.setState({ loading: false });
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ export type TypesStoreType = {
|
||||||
setTemplates: (newState: {}) => void;
|
setTemplates: (newState: {}) => void;
|
||||||
data: APIDataType;
|
data: APIDataType;
|
||||||
setData: (newState: {}) => void;
|
setData: (newState: {}) => void;
|
||||||
getTypes: () => Promise<void>;
|
getTypes: (force_refresh?: boolean) => Promise<void>;
|
||||||
ComponentFields: Set<string>;
|
ComponentFields: Set<string>;
|
||||||
setComponentFields: (fields: Set<string>) => void;
|
setComponentFields: (fields: Set<string>) => void;
|
||||||
addComponentField: (field: string) => void;
|
addComponentField: (field: string) => void;
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ def test_get_project_data():
|
||||||
async def test_create_or_update_starter_projects(client):
|
async def test_create_or_update_starter_projects(client):
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
# Run the function to create or update projects
|
# Run the function to create or update projects
|
||||||
create_or_update_starter_projects()
|
await create_or_update_starter_projects()
|
||||||
|
|
||||||
# Get the number of projects returned by load_starter_projects
|
# Get the number of projects returned by load_starter_projects
|
||||||
num_projects = len(load_starter_projects())
|
num_projects = len(load_starter_projects())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue