Skip to content

Commit 308172a

Browse files
authored
Merge pull request #111 from reconurge/feat/node-refactor
feat: big codebase refactor + new node display features
2 parents aa1e39b + 138bbb0 commit 308172a

File tree

184 files changed

+7824
-4497
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

184 files changed

+7824
-4497
lines changed

Makefile

Lines changed: 113 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,140 @@
11
PROJECT_ROOT := $(shell pwd)
22

3-
.PHONY: install run stop stop-dev stop-prod infra api frontend celery clean dev prod check-env build-dev build-prod open-browser test
4-
ENV_DIRS := . flowsint-api flowsint-core flowsint-app
5-
6-
open-browser:
7-
@echo "⏳ Waiting for frontend to be ready..."
8-
@bash -c 'until curl -s http://localhost:5173 > /dev/null 2>&1; do sleep 1; done'
9-
@echo "🌐 Opening browser..."
10-
@open http://localhost:5173 2>/dev/null || xdg-open http://localhost:5173 2>/dev/null || echo "✅ Flowsint ready at http://localhost:5173"
3+
export DOCKER_BUILDKIT=0
4+
export COMPOSE_PARALLEL_LIMIT=1
115

12-
dev:
13-
@echo "🐙 Starting Flowsint in DEVELOPMENT mode..."
14-
$(MAKE) check-env
15-
docker compose -f docker-compose.dev.yml up --build -d
16-
$(MAKE) open-browser
17-
docker compose -f docker-compose.dev.yml logs -f
18-
19-
prod:
20-
@echo "🐙 Starting Flowsint in PRODUCTION mode..."
21-
$(MAKE) check-env
22-
docker compose -f docker-compose.prod.yml up --build -d
23-
$(MAKE) open-browser
6+
COMPOSE_DEV := docker compose -f docker-compose.dev.yml
7+
COMPOSE_PROD := docker compose -f docker-compose.prod.yml
248

25-
build-dev:
26-
@echo "🔨 Building development images..."
27-
docker compose -f docker-compose.dev.yml build
9+
.PHONY: \
10+
dev prod \
11+
build-dev build-prod \
12+
up-dev up-prod down \
13+
infra-dev infra-prod infra-stop-dev infra-stop-prod \
14+
migrate-dev migrate-prod \
15+
api frontend celery \
16+
test install clean check-env open-browser
2817

29-
build-prod:
30-
@echo "🔨 Building production images..."
31-
docker compose -f docker-compose.prod.yml build
18+
ENV_DIRS := . flowsint-api flowsint-core flowsint-app
3219

3320
check-env:
34-
@echo "🔎 Checking .env files..."
21+
@echo "Checking .env files..."
3522
@for dir in $(ENV_DIRS); do \
3623
env_file="$$dir/.env"; \
3724
env_example="$(PROJECT_ROOT)/.env.example"; \
38-
if [ -f "$$env_file" ]; then \
39-
echo "✅ Using existing .env in $$dir"; \
40-
else \
41-
echo "⚠️ .env missing in $$dir, copying from .env.example"; \
25+
if [ ! -f "$$env_file" ]; then \
4226
cp "$$env_example" "$$env_file"; \
27+
echo "Created $$env_file"; \
4328
fi; \
4429
done
4530

46-
test:
47-
@echo "🔎 Running tests..."
48-
cd $(PROJECT_ROOT)/flowsint-types && poetry run pytest
49-
cd $(PROJECT_ROOT)/flowsint-core && poetry run pytest
50-
cd $(PROJECT_ROOT)/flowsint-enrichers && poetry run pytest
31+
open-browser:
32+
@echo "Waiting for frontend..."
33+
@bash -c 'until curl -s http://localhost:5173 > /dev/null 2>&1; do sleep 1; done'
34+
@open http://localhost:5173 2>/dev/null || \
35+
xdg-open http://localhost:5173 2>/dev/null || \
36+
echo "Frontend ready at http://localhost:5173"
5137

52-
install:
53-
@echo "🐙 Installing Flowsint project modules..."
54-
@if ! command -v poetry >/dev/null 2>&1; then \
55-
echo "⚠️ Poetry is not installed. Please install it:"; \
56-
echo "pipx install poetry"; \
57-
echo "or"; \
58-
echo "curl -sSL https://install.python-poetry.org | python3 -"; \
59-
exit 1; \
38+
build-dev:
39+
@echo "Building DEV images..."
40+
$(COMPOSE_DEV) build
41+
42+
build-prod:
43+
@echo "Building PROD images..."
44+
$(COMPOSE_PROD) build
45+
46+
infra-dev:
47+
@echo "Starting DEV infra (postgres / redis / neo4j)..."
48+
$(COMPOSE_DEV) up -d postgres redis neo4j
49+
50+
infra-prod:
51+
@echo "Starting PROD infra (postgres / redis / neo4j)..."
52+
$(COMPOSE_PROD) up -d postgres redis neo4j
53+
54+
infra-stop-dev:
55+
@echo "Stopping DEV infra..."
56+
$(COMPOSE_DEV) stop postgres redis neo4j
57+
58+
infra-stop-prod:
59+
@echo "Stopping PROD infra..."
60+
$(COMPOSE_PROD) stop postgres redis neo4j
61+
62+
migrate-dev:
63+
@echo "Running DEV migrations..."
64+
@if ! $(COMPOSE_DEV) ps -q neo4j | grep -q .; then \
65+
echo "Neo4j not running → starting DEV infra"; \
66+
$(COMPOSE_DEV) up -d --wait neo4j; \
6067
fi
61-
poetry config virtualenvs.in-project true --local
62-
docker compose up -d postgres redis neo4j
63-
poetry install
64-
cd $(PROJECT_ROOT)/flowsint-core && poetry install
65-
cd $(PROJECT_ROOT)/flowsint-enrichers && poetry install
66-
cd $(PROJECT_ROOT)/flowsint-api && poetry install && poetry run alembic upgrade head
67-
@echo "✅ All modules installed successfully!"
68+
yarn migrate
69+
70+
migrate-prod:
71+
@echo "⚠️ Running PROD migrations"
72+
@echo "This will ALTER production data."
73+
@read -p "Type 'prod' to continue: " confirm; \
74+
if [ "$$confirm" != "prod" ]; then \
75+
echo "Aborted."; exit 1; \
76+
fi
77+
yarn migrate
6878

69-
infra:
70-
docker compose up -d
79+
dev:
80+
@echo "Starting DEV environment..."
81+
$(MAKE) check-env
82+
$(MAKE) infra-dev
83+
$(MAKE) migrate-dev
84+
$(MAKE) build-dev
85+
$(MAKE) up-dev
86+
$(MAKE) open-browser
87+
$(COMPOSE_DEV) logs -f
7188

72-
api:
73-
cd $(PROJECT_ROOT)/flowsint-api && poetry run uvicorn app.main:app --host 0.0.0.0 --port 5001 --reload
89+
prod:
90+
@echo "Starting PROD environment..."
91+
$(MAKE) check-env
92+
$(MAKE) build-prod
93+
$(MAKE) up-prod
7494

75-
frontend:
76-
@echo "🐙 Starting frontend and opening browser..."
77-
@docker compose up -d flowsint-app
78-
@bash -c 'until curl -s http://localhost:5173 > /dev/null 2>&1; do sleep 1; done; open http://localhost:5173 2>/dev/null || xdg-open http://localhost:5173 2>/dev/null || echo "✅ Frontend ready at http://localhost:5173"'
95+
up-dev:
96+
$(COMPOSE_DEV) up -d --no-build
7997

80-
frontend_prod:
81-
cd $(PROJECT_ROOT)/flowsint-app && npm run build
98+
up-prod:
99+
$(COMPOSE_PROD) up -d --no-build
82100

83-
celery:
84-
cd $(PROJECT_ROOT)/flowsint-core && poetry run celery -A flowsint_core.core.celery worker --loglevel=info --pool=threads --concurrency=10
101+
down:
102+
-$(COMPOSE_DEV) down
103+
-$(COMPOSE_PROD) down
85104

86-
run:
87-
@echo "🐙 Starting all services..."
88-
docker compose up -d
89-
@echo "⏳ Waiting for frontend to be ready..."
90-
@bash -c 'until curl -s http://localhost:5173 > /dev/null 2>&1; do sleep 1; done'
91-
@echo "🌐 Opening browser..."
92-
@open http://localhost:5173 2>/dev/null || xdg-open http://localhost:5173 2>/dev/null || echo "✅ All services ready! Flowsint at http://localhost:5173"
93-
$(MAKE) -j2 api celery
105+
api:
106+
cd $(PROJECT_ROOT)/flowsint-api && \
107+
poetry run uvicorn app.main:app --host 0.0.0.0 --port 5001 --reload
94108

95-
stop:
96-
@echo "🛑 Stopping all services..."
97-
-docker compose -f docker-compose.dev.yml down
98-
-docker compose -f docker-compose.prod.yml down
99-
-docker compose down
109+
frontend:
110+
$(COMPOSE_DEV) up -d flowsint-app
111+
$(MAKE) open-browser
112+
113+
celery:
114+
cd $(PROJECT_ROOT)/flowsint-core && \
115+
poetry run celery -A flowsint_core.core.celery \
116+
worker --loglevel=info --pool=threads --concurrency=10
100117

101-
stop-dev:
102-
@echo "🛑 Stopping development services..."
103-
docker compose -f docker-compose.dev.yml down
118+
test:
119+
cd flowsint-types && poetry run pytest
120+
cd flowsint-core && poetry run pytest
121+
cd flowsint-enrichers && poetry run pytest
104122

105-
stop-prod:
106-
@echo "🛑 Stopping production services..."
107-
docker compose -f docker-compose.prod.yml down
123+
install:
124+
poetry config virtualenvs.in-project true --local
125+
$(MAKE) infra-dev
126+
poetry install
127+
cd flowsint-core && poetry install
128+
cd flowsint-enrichers && poetry install
129+
cd flowsint-api && poetry install && poetry run alembic upgrade head
108130

109131
clean:
110-
@echo "⚠️ WARNING: This will remove ALL Docker containers, images, volumes, and virtual environments."
111-
@echo "⚠️ ALL DATA in databases and volumes will be permanently deleted!"
112-
@echo ""
113-
@read -p "Are you sure you want to continue? [y/N]: " confirm; \
114-
if [ "$$confirm" != "y" ] && [ "$$confirm" != "Y" ]; then \
115-
echo "❌ Cleanup cancelled."; \
116-
exit 1; \
117-
fi
118-
@echo "🧹 Removing containers, images, volumes and venvs..."
119-
-docker compose -f docker-compose.dev.yml down -v --rmi all --remove-orphans
120-
-docker compose -f docker-compose.prod.yml down -v --rmi all --remove-orphans
121-
-docker compose down -v --rmi all --remove-orphans
122-
rm -rf $(PROJECT_ROOT)/flowsint-app/node_modules
123-
rm -rf $(PROJECT_ROOT)/flowsint-core/.venv
124-
rm -rf $(PROJECT_ROOT)/flowsint-enrichers/.venv
125-
rm -rf $(PROJECT_ROOT)/flowsint-api/.venv
126-
@echo "✅ Cleanup complete!"
132+
@echo "This will remove ALL Docker data. Continue? [y/N]"
133+
@read confirm; \
134+
if [ "$$confirm" != "y" ]; then exit 1; fi
135+
-$(COMPOSE_DEV) down -v --rmi all --remove-orphans
136+
-$(COMPOSE_PROD) down -v --rmi all --remove-orphans
137+
rm -rf flowsint-app/node_modules
138+
rm -rf flowsint-core/.venv
139+
rm -rf flowsint-enrichers/.venv
140+
rm -rf flowsint-api/.venv

docker-compose.dev.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ services:
5858
networks:
5959
- flowsint_network
6060
healthcheck:
61-
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:7474 || exit 1"]
62-
interval: 10s
61+
test: cypher-shell -u ${NEO4J_USERNAME} -p ${NEO4J_PASSWORD} "RETURN 1"
62+
interval: 5s
6363
timeout: 5s
64-
retries: 5
64+
retries: 10
6565

6666
# FastAPI Backend
6767
api:

docker-compose.prod.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ services:
5959
networks:
6060
- flowsint_network
6161
healthcheck:
62-
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:7474 || exit 1"]
63-
interval: 10s
62+
test: cypher-shell -u ${NEO4J_USERNAME} -p ${NEO4J_PASSWORD} "RETURN 1"
63+
interval: 5s
6464
timeout: 5s
65-
retries: 5
65+
retries: 10
6666

6767
# FastAPI Backend (Production)
6868
api:

docker-compose.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ services:
4444
- neo4j_logs:/logs
4545
- neo4j_import:/var/lib/neo4j/import
4646
- neo4j_plugins:/plugins
47+
healthcheck:
48+
test: cypher-shell -u ${NEO4J_USERNAME} -p ${NEO4J_PASSWORD} "RETURN 1"
49+
interval: 5s
50+
timeout: 5s
51+
retries: 10
4752
restart: unless-stopped
4853
networks:
4954
- flowsint_network

flowsint-api/app/api/routes/enrichers.py

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
1-
from fastapi import APIRouter, HTTPException, Depends, Query
2-
from typing import List, Any, Optional
3-
from pydantic import BaseModel
4-
from flowsint_enrichers import ENRICHER_REGISTRY, load_all_enrichers
1+
from typing import Any, List, Optional
2+
3+
from fastapi import APIRouter, Depends, HTTPException, Query
54
from flowsint_core.core.celery import celery
6-
from flowsint_core.core.types import Node, Edge, FlowBranch
5+
from flowsint_core.core.graph import create_graph_service, GraphEdge, GraphNode
76
from flowsint_core.core.models import CustomType, Profile
8-
from flowsint_core.core.graph_repository import GraphRepository
9-
from flowsint_types import clean_neo4j_node_data
10-
from app.api.deps import get_current_user
117
from flowsint_core.core.postgre_db import get_db
12-
from sqlalchemy.orm import Session
8+
from flowsint_core.core.types import FlowBranch
9+
from flowsint_enrichers import ENRICHER_REGISTRY, load_all_enrichers
10+
from pydantic import BaseModel
1311
from sqlalchemy import func
12+
from sqlalchemy.orm import Session
13+
14+
from app.api.deps import get_current_user
1415

1516
# Auto-discover and register all enrichers
1617
load_all_enrichers()
1718

1819

1920
class FlowComputationRequest(BaseModel):
20-
nodes: List[Node]
21-
edges: List[Edge]
21+
nodes: List[GraphNode]
22+
edges: List[GraphEdge]
2223
inputType: Optional[str] = None
2324

2425

@@ -74,21 +75,20 @@ async def launch_enricher(
7475
):
7576
try:
7677
# Retrieve nodes from Neo4J by their element IDs
77-
graph_repo = GraphRepository()
78-
nodes_data = graph_repo.get_nodes_by_ids(payload.node_ids, payload.sketch_id)
79-
80-
if not nodes_data:
81-
raise HTTPException(status_code=404, detail="No nodes found with provided IDs")
82-
83-
# Clean Neo4J-specific fields from node data
84-
# The enricher's preprocess() will handle Pydantic validation
85-
cleaned_nodes = [clean_neo4j_node_data(node_data) for node_data in nodes_data]
86-
78+
graph_service = create_graph_service(sketch_id=payload.sketch_id)
79+
entities = graph_service.get_nodes_by_ids_for_task(payload.node_ids)
80+
81+
# send deserialized nodes
82+
entities = [entity.model_dump(mode="json", serialize_as_any=True) for entity in entities]
83+
if not entities:
84+
raise HTTPException(
85+
status_code=404, detail="No entities found with provided IDs"
86+
)
8787
task = celery.send_task(
8888
"run_enricher",
8989
args=[
9090
enricher_name,
91-
cleaned_nodes,
91+
entities,
9292
payload.sketch_id,
9393
str(current_user.id),
9494
],
@@ -98,4 +98,7 @@ async def launch_enricher(
9898
except HTTPException:
9999
raise
100100
except Exception as e:
101-
raise HTTPException(status_code=500, detail=f"Error launching enricher: {str(e)}")
101+
print(e)
102+
raise HTTPException(
103+
status_code=500, detail=f"Error launching enricher: {str(e)}"
104+
)

0 commit comments

Comments
 (0)