Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
224 commits
Select commit Hold shift + click to select a range
d2b2e6f
Remove workbench column from projects_table
giancarloromeo Jul 22, 2025
d78aa5c
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
giancarloromeo Jul 23, 2025
47072ad
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
giancarloromeo Jul 24, 2025
6cc38ae
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
giancarloromeo Jul 25, 2025
f6ae1d7
fix: remove workbench from faker factory
giancarloromeo Jul 25, 2025
20cef27
fix: remove workbench references from catalog
giancarloromeo Jul 25, 2025
b9cc19c
Merge branch 'master' into pr/giancarloromeo/8141
pcrespov Jul 28, 2025
e920c1f
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
pcrespov Jul 28, 2025
2637c2c
Merge branch 'is5646/use-project-nodes-table-instead-of-workbench' of…
pcrespov Jul 28, 2025
77d26ec
fixes projecst repo
pcrespov Jul 28, 2025
c209c6b
fixes tests modules
pcrespov Jul 28, 2025
5b7935a
faker
pcrespov Jul 28, 2025
019e04b
fixing nodes
pcrespov Jul 28, 2025
9c0640e
fixing fakes
pcrespov Jul 28, 2025
f7cf17b
fixing fakes
pcrespov Jul 28, 2025
17f60de
fixes update
pcrespov Jul 28, 2025
1c9de98
minor
pcrespov Jul 28, 2025
764a386
Merge branch 'master' into pr/giancarloromeo/8141
pcrespov Jul 28, 2025
360dcb4
fixes migration tests
pcrespov Jul 28, 2025
86e02d6
fixes
pcrespov Jul 28, 2025
d1510e5
simplified fixture
pcrespov Jul 28, 2025
791e8b3
comment
pcrespov Jul 28, 2025
00370e5
fix: create_node fixture
giancarloromeo Jul 28, 2025
398866c
Merge branch 'is5646/use-project-nodes-table-instead-of-workbench' of…
giancarloromeo Jul 28, 2025
54028fb
fix: move project_exists
giancarloromeo Jul 28, 2025
5f6f274
Merge branch 'is5646/use-project-nodes-table-instead-of-workbench' of…
pcrespov Jul 28, 2025
caa2799
rename
pcrespov Jul 28, 2025
6615e9b
rm project dependency
pcrespov Jul 28, 2025
8181580
Updates Node model and cleanup
pcrespov Jul 28, 2025
7e1fb26
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
pcrespov Jul 28, 2025
cce82cb
Merge branch 'is5646/use-project-nodes-table-instead-of-workbench' of…
pcrespov Jul 28, 2025
86846a6
Merge remote-tracking branch 'upstream/master' into is5646/use-projec…
giancarloromeo Jul 29, 2025
e33be86
fix: use annotated functional validators
giancarloromeo Jul 29, 2025
5bce45d
fix: fixtures still using workbench
giancarloromeo Jul 29, 2025
a0d89e4
fix: paths with problematic names
giancarloromeo Jul 29, 2025
b58f26f
fix: RPC tests
giancarloromeo Jul 29, 2025
2700ee6
fix: minor
giancarloromeo Jul 29, 2025
14f50e6
fix: frontend data generator
giancarloromeo Jul 29, 2025
43630d5
fix: project_id type
giancarloromeo Jul 29, 2025
243c5e8
fix: unpack created project/nodes
giancarloromeo Jul 29, 2025
427f998
fix: unpack
giancarloromeo Jul 29, 2025
841593d
fix: clone test
giancarloromeo Jul 29, 2025
dbf42b6
fix: project_nodes
giancarloromeo Jul 29, 2025
3b8a3ba
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
giancarloromeo Jul 29, 2025
1adee7e
fix: node names mapping
giancarloromeo Jul 29, 2025
2961b6f
fix: nullable workbench
giancarloromeo Jul 30, 2025
f5ae1c5
fix: exclude workbench from validation
giancarloromeo Jul 30, 2025
d9881a1
fix: validate ignoring workbench
giancarloromeo Jul 30, 2025
1ceff4d
fix: temp include workbench on a validation
giancarloromeo Jul 30, 2025
a47e4c8
fix: folder body
giancarloromeo Jul 30, 2025
45a07b8
fix: workbench
giancarloromeo Jul 30, 2025
03acbd8
fix: remove workbench
giancarloromeo Jul 30, 2025
b16810c
fix: workbench
giancarloromeo Jul 30, 2025
6558b5a
fix: webserver
giancarloromeo Jul 30, 2025
2bc186d
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
giancarloromeo Jul 31, 2025
adb9897
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
giancarloromeo Jul 31, 2025
67c2183
fix: workbench
giancarloromeo Jul 31, 2025
6048085
Merge branch 'is5646/use-project-nodes-table-instead-of-workbench' of…
giancarloromeo Jul 31, 2025
4455d50
fix: use batch call
giancarloromeo Jul 31, 2025
2954940
Merge remote-tracking branch 'upstream/master' into is5646/use-projec…
giancarloromeo Aug 4, 2025
0eec938
storage: returns minimal tuple
pcrespov Aug 4, 2025
d52d3e7
proper migration project.workbench
pcrespov Aug 4, 2025
30b2b7f
using insert_and_get_row
pcrespov Aug 4, 2025
38da394
fixes logs
pcrespov Aug 4, 2025
a0b71bb
doc
pcrespov Aug 4, 2025
ab0a810
fix: projects states handlers
giancarloromeo Aug 5, 2025
e86fe27
fix: typecheck
giancarloromeo Aug 5, 2025
ae80167
fix: typecheck
giancarloromeo Aug 5, 2025
5dde879
fix: relative import
giancarloromeo Aug 5, 2025
a2a8a27
fix: typecheck
giancarloromeo Aug 5, 2025
f4fd950
fix: extract workbench
giancarloromeo Aug 5, 2025
3a25b02
fix: use workbench subquery
giancarloromeo Aug 5, 2025
a4cbb9a
fix: use workbench subquery
giancarloromeo Aug 5, 2025
e5de7b1
fix: get project with workbench
giancarloromeo Aug 5, 2025
907708b
fix: imports
giancarloromeo Aug 5, 2025
3156531
fix: inputs required nullability
giancarloromeo Aug 5, 2025
7b07b66
fix: typecheck
giancarloromeo Aug 5, 2025
0a3d8d7
fix: project cancellation
giancarloromeo Aug 5, 2025
4f43294
Merge branch 'is5646/use-project-nodes-table-instead-of-workbench' of…
pcrespov Aug 5, 2025
e327c6b
model_dump_as_node
pcrespov Aug 5, 2025
ded3e8d
fixes fixture
pcrespov Aug 5, 2025
9c23c06
cleanup
pcrespov Aug 5, 2025
994cc0d
fixes workbench retrieval
pcrespov Aug 5, 2025
2ce1cc6
fixes insert batch
pcrespov Aug 5, 2025
b0f1626
Merge branch 'master' into pr/giancarloromeo/8141
pcrespov Aug 5, 2025
a9b80b2
no need to restor workbench
pcrespov Aug 5, 2025
087ec30
remove define `_projects_service.get_project_for_user`
pcrespov Aug 5, 2025
7b2639c
fix: validate workbench against nodes
giancarloromeo Aug 5, 2025
1770502
fix: return project with workbench when creating
giancarloromeo Aug 5, 2025
5b213c0
fix: create project fixture
giancarloromeo Aug 5, 2025
ea67751
fix: workbench when share workpace
giancarloromeo Aug 6, 2025
9295602
fix: workbench when getting workspaces
giancarloromeo Aug 6, 2025
58549f7
fix: include None
giancarloromeo Aug 6, 2025
41d4182
fix: extract only not nulls
giancarloromeo Aug 6, 2025
9b892c1
Merge remote-tracking branch 'upstream/master' into is5646/use-projec…
giancarloromeo Aug 6, 2025
6ac876d
Merge remote-tracking branch 'upstream/master' into is5646/use-projec…
giancarloromeo Aug 6, 2025
d4b90ff
Add trigger/function when updating project nodes
giancarloromeo Aug 7, 2025
d95331f
Fix script
giancarloromeo Aug 7, 2025
a797222
fix: delete project_node
giancarloromeo Aug 7, 2025
bf033d2
remove unused
giancarloromeo Aug 7, 2025
c9c6a1e
fix: script downgrade order
giancarloromeo Aug 7, 2025
73e8ca1
fix: test
giancarloromeo Aug 7, 2025
9e0e95f
fix: lastChangeDate assert
giancarloromeo Aug 7, 2025
790feaf
fix: test
giancarloromeo Aug 7, 2025
b81f5b2
fix: node creation
giancarloromeo Aug 7, 2025
f41304c
typecheck
giancarloromeo Aug 7, 2025
86c5a75
typecheck
giancarloromeo Aug 7, 2025
b0b2667
remove old
giancarloromeo Aug 7, 2025
726cdc3
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
giancarloromeo Aug 7, 2025
0a16f40
remove unused
giancarloromeo Aug 7, 2025
fba3af1
use new repo
giancarloromeo Aug 7, 2025
9a7c654
remove get project
giancarloromeo Aug 7, 2025
725be27
update nodes
giancarloromeo Aug 8, 2025
5e14001
fix document creation
giancarloromeo Aug 8, 2025
0cecabd
fix tests
giancarloromeo Aug 8, 2025
f8fa9e6
fix test
giancarloromeo Aug 8, 2025
8ffa91b
fix tests
giancarloromeo Aug 8, 2025
e5a9b5f
fix
giancarloromeo Aug 8, 2025
42ee9d1
fix deepdiff
giancarloromeo Aug 8, 2025
661b5a5
remove tests
giancarloromeo Aug 8, 2025
325608c
fix model_dump
giancarloromeo Aug 8, 2025
127e90a
fix
giancarloromeo Aug 8, 2025
df2e204
fix test
giancarloromeo Aug 8, 2025
824200a
fix int test
giancarloromeo Aug 8, 2025
c69df79
tests: ignore order
giancarloromeo Aug 11, 2025
6c0431f
fix: inputs required
giancarloromeo Aug 11, 2025
ee01c01
fix: node outputs
giancarloromeo Aug 11, 2025
6a51b9a
fix: more efficient get product
giancarloromeo Aug 11, 2025
77762b3
refactor: remove access to workbench
giancarloromeo Aug 12, 2025
289544c
Fix bug
matusdrobuliak66 Aug 12, 2025
c8d26b5
Merge remote-tracking branch 'matusdrobuliak66/fix-access-rights-work…
giancarloromeo Aug 12, 2025
7db6618
fix: project node states
giancarloromeo Aug 12, 2025
9fb1220
fix: project states
giancarloromeo Aug 13, 2025
5757eb8
fix: validator
giancarloromeo Aug 13, 2025
19834d2
fix: get project with None
giancarloromeo Aug 13, 2025
bbc6560
fix: get project
giancarloromeo Aug 13, 2025
393e7db
fix: tags
giancarloromeo Aug 13, 2025
546003f
fix: workbench
giancarloromeo Aug 13, 2025
21a4ed0
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
giancarloromeo Aug 13, 2025
e2df3dd
fix: get project response
giancarloromeo Aug 13, 2025
2f611c3
Merge branch 'is5646/use-project-nodes-table-instead-of-workbench' of…
giancarloromeo Aug 13, 2025
20f70f6
fix: workbench
giancarloromeo Aug 13, 2025
1319020
fix: node state
giancarloromeo Aug 13, 2025
bfa1685
remove workbench
giancarloromeo Aug 13, 2025
044edc5
fix: repo
giancarloromeo Aug 14, 2025
de831c4
fix: new syntax
giancarloromeo Aug 14, 2025
9dada93
fix: include unset
giancarloromeo Aug 14, 2025
d453f76
tests: prettify deepdiff
giancarloromeo Aug 14, 2025
f29cf8c
fix: test
giancarloromeo Aug 14, 2025
7928dfb
fix: model dump without aliases
giancarloromeo Aug 14, 2025
88c3159
typecheck
giancarloromeo Aug 14, 2025
d01e3c3
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
giancarloromeo Aug 14, 2025
5dd1c82
fix: node creation
giancarloromeo Aug 14, 2025
c1826f8
fix: typecheck
giancarloromeo Aug 14, 2025
ae75ac1
fix: node creation
giancarloromeo Aug 14, 2025
3547a21
typecheck
giancarloromeo Aug 14, 2025
6104f45
fix: response
giancarloromeo Aug 15, 2025
994adda
fix: match
giancarloromeo Aug 15, 2025
f6ba587
fix: nullability
giancarloromeo Aug 15, 2025
da63986
fix test
giancarloromeo Aug 15, 2025
0df85db
remove workbench
giancarloromeo Aug 15, 2025
e9793e1
fix: project creation with nodes
giancarloromeo Aug 15, 2025
198bb4b
clean
giancarloromeo Aug 15, 2025
2748c5a
remove unused
giancarloromeo Aug 15, 2025
f4655a9
remove fixme
giancarloromeo Aug 15, 2025
b8c966e
fix: streams
giancarloromeo Aug 15, 2025
8eabd50
fix relative
giancarloromeo Aug 15, 2025
a415e87
fix: revert casing
giancarloromeo Aug 15, 2025
13bbe34
fix random
giancarloromeo Aug 15, 2025
99c2eb7
rename
giancarloromeo Aug 15, 2025
7e3bbe9
fix helper
giancarloromeo Aug 15, 2025
7d71e9f
fix
giancarloromeo Aug 15, 2025
c946376
fix
giancarloromeo Aug 15, 2025
6972a84
fix
giancarloromeo Aug 15, 2025
3bf0399
fix
giancarloromeo Aug 15, 2025
6f2dbf3
fix warnings logs
giancarloromeo Aug 15, 2025
f325339
remove position
giancarloromeo Aug 15, 2025
3464789
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
giancarloromeo Aug 15, 2025
bb16e26
fix
giancarloromeo Aug 15, 2025
e918dce
Merge branches 'is5646/use-project-nodes-table-instead-of-workbench' …
giancarloromeo Aug 15, 2025
df073b1
fix tests
giancarloromeo Aug 15, 2025
89404b9
fix
giancarloromeo Aug 15, 2025
669b4a8
fix
giancarloromeo Aug 15, 2025
6105bda
fix logs
giancarloromeo Aug 15, 2025
22d39ed
fix
giancarloromeo Aug 15, 2025
1b53a30
fix
giancarloromeo Aug 15, 2025
75d7e55
fix
giancarloromeo Aug 15, 2025
b82302f
fix
giancarloromeo Aug 15, 2025
e12c40b
fix
giancarloromeo Aug 15, 2025
9dfe2df
revert models
giancarloromeo Aug 15, 2025
88f91f5
fix: improve listing
giancarloromeo Aug 18, 2025
db156e4
fix: script
giancarloromeo Aug 18, 2025
6e17b80
fix: connection
giancarloromeo Aug 18, 2025
c5a12a0
Merge remote-tracking branch 'upstream/master' into is5646/use-projec…
giancarloromeo Aug 18, 2025
b7bb036
fix
giancarloromeo Aug 18, 2025
ec1d762
fix: model dump
giancarloromeo Aug 19, 2025
5718e92
try to fix
giancarloromeo Aug 19, 2025
260c4ab
try to fix 2.0
giancarloromeo Aug 19, 2025
cc86d53
fix: workbench nulls
giancarloromeo Aug 19, 2025
413f4dc
fix: test
giancarloromeo Aug 19, 2025
6780a88
Merge branch 'master' into pr/giancarloromeo/8141
pcrespov Aug 22, 2025
fb3179e
fix: alembic
giancarloromeo Aug 22, 2025
ed060af
fix: typecheck
giancarloromeo Aug 22, 2025
ac12cba
fix: duplicate by_alias
giancarloromeo Aug 22, 2025
eafc2d3
updates webserver OAS
pcrespov Aug 22, 2025
f9483cb
fixes update node's states
pcrespov Aug 22, 2025
6b0048f
fixes mypy
pcrespov Aug 22, 2025
c93168a
fixes test listerner
pcrespov Aug 22, 2025
c66590d
fixes test helper
pcrespov Aug 22, 2025
f3512b3
db returns None. sa.func.json_strip_nulls -> sa.func.json
pcrespov Aug 22, 2025
08f1138
Merge branch 'master' into is5646/use-project-nodes-table-instead-of-…
pcrespov Aug 22, 2025
fb73d03
type
pcrespov Aug 22, 2025
4217743
Merge branch 'master' into pr/giancarloromeo/8141
pcrespov Sep 4, 2025
7c6197d
Adapts revisitons
pcrespov Sep 4, 2025
4b70868
fix
pcrespov Sep 4, 2025
a74ec78
Merge branch 'master' into pr/giancarloromeo/8141
pcrespov Sep 11, 2025
a928398
Merge branch 'master' into pr/giancarloromeo/8141
pcrespov Sep 12, 2025
55da438
uses adapters
pcrespov Sep 12, 2025
1e52c3c
minor
pcrespov Sep 12, 2025
2ec1124
bad sort
pcrespov Sep 12, 2025
a4bc47c
Merge branch 'master' into pr/giancarloromeo/8141
pcrespov Sep 17, 2025
22ddd71
its really a float
pcrespov Sep 17, 2025
4ef9dd2
updates OAS
pcrespov Sep 17, 2025
037272b
updates down revision in pg migration
pcrespov Sep 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -354,8 +354,12 @@ class Node(BaseModel):
Field(default_factory=NodeState, description="The node's state object"),
] = DEFAULT_FACTORY

# NOTE: requested_resources should be here! WARNING: this model is used both in database and rest api!
# Model for project_nodes table should NOT be Node but a different one !
required_resources: Annotated[
dict[str, Any] | None,
Field(default_factory=dict),
# NOTE: requested_resources should be here! WARNING: this model is used both in database and rest api!
# Model for project_nodes table should NOT be Node but a different one !
] = DEFAULT_FACTORY

boot_options: Annotated[
dict[EnvVarKey, str] | None,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,337 @@
"""Remove workbench column from projects_table

Revision ID: 201aa37f4d9a
Revises: 06eafd25d004
Create Date: 2025-07-22 19:25:42.125196+00:00

"""

import json
from typing import Any

import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = "201aa37f4d9a"
down_revision = "7e92447558e0"
branch_labels = None
depends_on = None


def _migrate_workbench_to_projects_nodes() -> None:
"""Migrate nodes from projects.workbench to projects_nodes table."""

# Get database connection
connection = op.get_bind()

# Fetch all projects with workbench data
projects_result = connection.execute(
sa.text("SELECT uuid, workbench FROM projects WHERE workbench IS NOT NULL")
)

errors: list[str] = []
updated_nodes_count = 0
inserted_nodes_count = 0

for project_uuid, workbench_json in projects_result:
if not workbench_json:
continue

try:
workbench_data = (
workbench_json
if isinstance(workbench_json, dict)
else json.loads(workbench_json)
)
except (json.JSONDecodeError, TypeError) as e:
errors.append(f"Project {project_uuid}: Invalid workbench JSON - {e}")
continue

if not isinstance(workbench_data, dict):
errors.append(f"Project {project_uuid}: Workbench is not a dictionary")
continue

for node_id, node_data in workbench_data.items():
if not isinstance(node_data, dict):
errors.append(
f"Project {project_uuid}, Node {node_id}: Node data is not a dictionary"
)
continue

# Validate required fields
missing_fields = []
if not node_data.get("key"):
missing_fields.append("key")
if not node_data.get("version"):
missing_fields.append("version")
if not node_data.get("label"):
missing_fields.append("label")

if missing_fields:
errors.append(
f"Project {project_uuid}, Node {node_id}: Missing required fields: {', '.join(missing_fields)}"
)
continue

# Check if node already exists
existing_node = connection.execute(
sa.text(
"SELECT project_node_id FROM projects_nodes WHERE project_uuid = :project_uuid AND node_id = :node_id"
),
{"project_uuid": project_uuid, "node_id": node_id},
).fetchone()

# Prepare node data for insertion/update
node_values = {
"project_uuid": project_uuid,
"node_id": node_id,
"key": node_data["key"],
"version": node_data["version"],
"label": node_data["label"],
"progress": node_data.get("progress"),
"thumbnail": node_data.get("thumbnail"),
"input_access": (
json.dumps(node_data["input_access"])
if node_data.get("input_access")
else None
),
"input_nodes": (
json.dumps(node_data["input_nodes"])
if node_data.get("input_nodes")
else None
),
"inputs": (
json.dumps(node_data["inputs"]) if node_data.get("inputs") else None
),
"inputs_required": (
json.dumps(node_data["inputs_required"])
if node_data.get("inputs_required")
else None
),
"inputs_units": (
json.dumps(node_data["inputs_units"])
if node_data.get("inputs_units")
else None
),
"output_nodes": (
json.dumps(node_data["output_nodes"])
if node_data.get("output_nodes")
else None
),
"outputs": (
json.dumps(node_data["outputs"])
if node_data.get("outputs")
else None
),
"run_hash": node_data.get(
"run_hash", node_data.get("runHash")
), # Handle both camelCase and snake_case
"state": (
json.dumps(node_data["state"]) if node_data.get("state") else None
),
"parent": node_data.get("parent"),
"boot_options": (
json.dumps(node_data["boot_options"])
if node_data.get("boot_options", node_data.get("bootOptions"))
else None
),
}

if existing_node:
# Update existing node
update_sql = """
UPDATE projects_nodes SET
key = :key,
version = :version,
label = :label,
progress = :progress,
thumbnail = :thumbnail,
input_access = :input_access::jsonb,
input_nodes = :input_nodes::jsonb,
inputs = :inputs::jsonb,
inputs_required = :inputs_required::jsonb,
inputs_units = :inputs_units::jsonb,
output_nodes = :output_nodes::jsonb,
outputs = :outputs::jsonb,
run_hash = :run_hash,
state = :state::jsonb,
parent = :parent,
boot_options = :boot_options::jsonb,
modified_datetime = NOW()
WHERE project_uuid = :project_uuid AND node_id = :node_id
"""
connection.execute(sa.text(update_sql), node_values)
updated_nodes_count += 1
print(f"Updated existing node {node_id} in project {project_uuid}")

else:
# Insert new node
insert_sql = """
INSERT INTO projects_nodes (
project_uuid, node_id, key, version, label, progress, thumbnail,
input_access, input_nodes, inputs, inputs_required, inputs_units,
output_nodes, outputs, run_hash, state, parent, boot_options,
required_resources, created_datetime, modified_datetime
) VALUES (
:project_uuid, :node_id, :key, :version, :label, :progress, :thumbnail,
:input_access::jsonb, :input_nodes::jsonb, :inputs::jsonb,
:inputs_required::jsonb, :inputs_units::jsonb, :output_nodes::jsonb,
:outputs::jsonb, :run_hash, :state::jsonb, :parent, :boot_options::jsonb,
'{}'::jsonb, NOW(), NOW()
)
"""
connection.execute(sa.text(insert_sql), node_values)
inserted_nodes_count += 1

print(
f"Migration summary: {inserted_nodes_count} nodes inserted, {updated_nodes_count} nodes updated"
)

if errors:
error_message = f"Migration failed with {len(errors)} errors:\n" + "\n".join(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so if I get it correctly the migration will run whatever happens right, and you will get some error printed in the logs. or do you rollback?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if drop of the table will be included in this PR, this code was kindly suggested by AI... we still have to check it

errors
)
print(error_message)
raise RuntimeError(error_message)


def _restore_workbench_from_projects_nodes() -> None:
"""Restore workbench data from projects_nodes table to projects.workbench column."""

# Get database connection
connection = op.get_bind()

# Get all projects that have nodes in projects_nodes
projects_with_nodes = connection.execute(
sa.text(
"""
SELECT DISTINCT project_uuid
FROM projects_nodes
ORDER BY project_uuid
"""
)
)

errors: list[str] = []
restored_projects_count = 0

for (project_uuid,) in projects_with_nodes:
# Fetch all nodes for this project
nodes_result = connection.execute(
sa.text(
"""
SELECT node_id, key, version, label, progress, thumbnail,
input_access, input_nodes, inputs, inputs_required, inputs_units,
output_nodes, outputs, run_hash, state, parent, boot_options
FROM projects_nodes
WHERE project_uuid = :project_uuid
ORDER BY node_id
"""
),
{"project_uuid": project_uuid},
)

workbench_data: dict[str, Any] = {}

for row in nodes_result:
node_id = row.node_id

# Build node data dictionary
node_data: dict[str, Any] = {
"key": row.key,
"version": row.version,
"label": row.label,
}

# Add optional fields if they exist
if row.progress is not None:
node_data["progress"] = float(row.progress)
if row.thumbnail:
node_data["thumbnail"] = row.thumbnail
if row.input_access:
node_data["inputAccess"] = row.input_access
if row.input_nodes:
node_data["inputNodes"] = row.input_nodes
if row.inputs:
node_data["inputs"] = row.inputs
if row.inputs_required:
node_data["inputsRequired"] = row.inputs_required
if row.inputs_units:
node_data["inputsUnits"] = row.inputs_units
if row.output_nodes:
node_data["outputNodes"] = row.output_nodes
if row.outputs:
node_data["outputs"] = row.outputs
if row.run_hash:
node_data["runHash"] = row.run_hash
if row.state:
node_data["state"] = row.state
if row.parent:
node_data["parent"] = row.parent
if row.boot_options:
node_data["bootOptions"] = row.boot_options

workbench_data[node_id] = node_data

if workbench_data:
try:
# Update the project with the restored workbench data
connection.execute(
sa.text(
"""
UPDATE projects
SET workbench = :workbench_data
WHERE uuid = :project_uuid
"""
),
{
"project_uuid": project_uuid,
"workbench_data": json.dumps(workbench_data),
},
)
restored_projects_count += 1

except Exception as e:
errors.append(
f"Project {project_uuid}: Failed to restore workbench data - {e}"
)

print(
f"Downgrade summary: {restored_projects_count} projects restored with workbench data"
)

if errors:
error_message = f"Downgrade failed with {len(errors)} errors:\n" + "\n".join(
errors
)
print(error_message)
raise RuntimeError(error_message)


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###

# Migrate workbench data to projects_nodes before dropping the column
_migrate_workbench_to_projects_nodes()

op.drop_column("projects", "workbench")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you sure about doing this right away? what if there is one thing missing in your migration?
Also, did you actually try out with production real data locally?

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"projects",
sa.Column(
"workbench",
postgresql.JSON(astext_type=sa.Text()),
autoincrement=False,
nullable=False,
),
)

# Restore workbench data from projects_nodes table
_restore_workbench_from_projects_nodes()
# ### end Alembic commands ###
Loading
Loading