feat(entity): trigger webhooks when entity update or created

This commit is contained in:
arkohut 2024-06-07 23:13:01 +08:00
parent a4d0ccc34e
commit 885629bf15
2 changed files with 49 additions and 7 deletions

View File

@ -73,7 +73,7 @@ def create_entity(library_id: int, entity: NewEntityParam, db: Session) -> Entit
db.add(db_entity) db.add(db_entity)
db.commit() db.commit()
db.refresh(db_entity) db.refresh(db_entity)
return db_entity return Entity(**db_entity.__dict__)
def get_entity_by_id(entity_id: int, db: Session) -> Entity | None: def get_entity_by_id(entity_id: int, db: Session) -> Entity | None:
@ -153,4 +153,4 @@ def update_entity(
setattr(db_entity, key, value) setattr(db_entity, key, value)
db.commit() db.commit()
db.refresh(db_entity) db.refresh(db_entity)
return db_entity return Entity(**db_entity.__dict__)

View File

@ -1,9 +1,11 @@
import httpx
import uvicorn import uvicorn
from fastapi import FastAPI, HTTPException, Depends, status, Query from fastapi import FastAPI, HTTPException, Depends, status, Query, Request
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from typing import List, Annotated from typing import List, Annotated
import asyncio
from .config import get_database_path from .config import get_database_path
import memos.crud as crud import memos.crud as crud
@ -94,9 +96,41 @@ def new_folder(
return crud.add_folder(library_id=library.id, folder=folder, db=db) return crud.add_folder(library_id=library.id, folder=folder, db=db)
async def trigger_webhooks(library, entity, request):
async with httpx.AsyncClient() as client:
tasks = []
for plugin in library.plugins:
if plugin.webhook_url:
location = str(
request.url_for(
"get_entity_by_id", library_id=library.id, entity_id=entity.id
)
)
task = client.post(
plugin.webhook_url,
json={"entity": entity.model_dump(mode="json")},
headers={"Location": location},
timeout=10.0, # Adding a timeout of 10 seconds
)
tasks.append(task)
responses = await asyncio.gather(*tasks, return_exceptions=True)
for plugin, response in zip(library.plugins, responses):
if isinstance(response, Exception):
print(f"Error triggering webhook for plugin {plugin.id}: {response}")
elif response.status_code >= 400:
print(
f"Error triggering webhook for plugin {plugin.id}: {response.status_code} - {response.text}"
)
@app.post("/libraries/{library_id}/entities", response_model=Entity) @app.post("/libraries/{library_id}/entities", response_model=Entity)
def new_entity( async def new_entity(
new_entity: NewEntityParam, library_id: int, db: Session = Depends(get_db) new_entity: NewEntityParam,
library_id: int,
request: Request,
db: Session = Depends(get_db),
): ):
library = crud.get_library_by_id(library_id, db) library = crud.get_library_by_id(library_id, db)
if library is None: if library is None:
@ -105,6 +139,7 @@ def new_entity(
) )
entity = crud.create_entity(library_id, new_entity, db) entity = crud.create_entity(library_id, new_entity, db)
await trigger_webhooks(library, entity, request)
return entity return entity
@ -156,10 +191,11 @@ def get_entity_by_id(library_id: int, entity_id: int, db: Session = Depends(get_
@app.put("/libraries/{library_id}/entities/{entity_id}", response_model=Entity) @app.put("/libraries/{library_id}/entities/{entity_id}", response_model=Entity)
def update_entity( async def update_entity(
library_id: int, library_id: int,
entity_id: int, entity_id: int,
updated_entity: UpdateEntityParam, updated_entity: UpdateEntityParam,
request: Request,
db: Session = Depends(get_db), db: Session = Depends(get_db),
): ):
entity = crud.get_entity_by_id(entity_id, db) entity = crud.get_entity_by_id(entity_id, db)
@ -169,7 +205,14 @@ def update_entity(
detail="Entity not found in the specified library", detail="Entity not found in the specified library",
) )
library = crud.get_library_by_id(library_id, db)
if library is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Library not found"
)
entity = crud.update_entity(entity_id, updated_entity, db) entity = crud.update_entity(entity_id, updated_entity, db)
await trigger_webhooks(library, entity, request)
return entity return entity
@ -206,7 +249,6 @@ def list_plugins(db: Session = Depends(get_db)):
return plugins return plugins
@app.post("/libraries/{library_id}/plugins", status_code=status.HTTP_204_NO_CONTENT) @app.post("/libraries/{library_id}/plugins", status_code=status.HTTP_204_NO_CONTENT)
def add_library_plugin( def add_library_plugin(
library_id: int, new_plugin: NewLibraryPluginParam, db: Session = Depends(get_db) library_id: int, new_plugin: NewLibraryPluginParam, db: Session = Depends(get_db)