Repository navigation
Replies: 7 comments
|
I support this idea. These resources were developed gradually over time. For each of them, the design and implementation were ad hoc, and we didn't have a "global picture" with a consistent and uniform principle. As we are moving toward to the direction of managing many resources, it becomes very critical to unify them for those benefits mentioned by @bobbai00. |
|
I support this idea. It would directly help #9362, which I’m looking into: loading operators at runtime instead of compiling them into the system. With the common primitives, operators could simply be another resource kind. Publishing an operator would create an immutable version, saved workflows could pin the operator version they were built with, and access control would decide who can use each operator, all without building a separate set of tables and endpoints just for operators. That would let the operator work focus on the engine side (registering and loading operators at runtime) instead of resource management. |
|
I support this as well. Right now each resource kind works like its own small system, and like you pointed out, that shows up for users too, since sharing a workflow and sharing a dataset don't behave the same way. One definition of a resource that every kind follows makes sense, especially with agents, conversations, and operators likely coming later. I'm curious about how resources refer to each other. A workflow already uses datasets, and the kinds you listed would probably reference other resources as well. The lineage table links a version to the versions it was derived from, but I didn't see where "this workflow uses this dataset version" would live. Is that meant to be one of the common primitives too, or left for each kind to handle on its own? |
|
I support this direction. Consolidating ownership, access control, and CRUD removes substantial duplication across services and makes adding new kinds like operators straightforward. Two suggestions for the detailed design:
|
|
I agree with this plan. I believe the codebase is in a good shape from design perspective and AI can easily do this refactor. For example, Amber engine is fully developed in its service and folder, its execution logic, caching and all features are finalized designs and implemented with human written test cases. This makes refactoring much easier because we know for sure that test cases are correct and human written so AI has an easy feedback loop. In this regard, I even support migrating to Go, if we want to refactor, it would be better to do it for a long term goal. |
|
I agree with this direction. This would be a great opportunity to consolidate and refactor our existing resource management mechanisms. I believe it would make our codebase much cleaner and easier to maintain. One concern I have is that different resources may have their own resource-specific operations and permissions. Would it make sense to keep the common CRUD and access control primitives while allowing each resource type to define additional operations and permission checks? This way, we could maintain a consistent foundation while preserving the flexibility needed for different resources. |
|
I support this proposal. Following @aicam's suggestion in #9377, here is what the agent changes proposed there need to read from the backend, so it can be considered in the design.
Also, I don't think my open agent PRs (#9423, #9424) conflict with this effort. Neither changes backend code or adds a call to a backend endpoint. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
How Texera manages resources today
Texera manages six kinds of resources: workflows, datasets, models, computing units, environments, and warehouses. By managing a resource I mean three things: creating, reading, updating, and deleting it (CRUD), keeping its versions, and controlling who can access it. Today each kind is managed by its own code: workflows and warehouses in the Dashboard Service, datasets and models in the File Service, computing units in the Computing Unit Managing Service, and environments in the computing unit itself.
Major Limitation: Resources Are Managed Ad-hoc
I think Texera's resource management has one major limitation: resources are managed ad-hoc. Each kind was built on its own, with its own tables, endpoints, and rules, and the codebase has no single definition of a resource that every kind follows. As a result, the same three things are done differently for each kind:
POST /workflow/create, but an environment withPOST /pve/db. A dataset is deleted withDELETE /dataset/{did}, but a workflow withPOST /workflow/delete.workflow_of_usertable for workflows, in anowner_uidcolumn for datasets and models, and in auidcolumn for the other kinds. The rules differ too: a user with read access can remove themselves from a shared workflow, but not from a shared dataset, and environments and warehouses cannot be shared at all.The codebase itself shows how far the kinds have drifted apart.
ResourceTables.scalawas added so that the access rules could be written once, but its own comment says that it fits only datasets and models, because workflows record ownership in a separate table and computing units have no public flag.Consequences: Backend Code Is Duplicated, Hard to Maintain, and Hard to Extend
The current backend codebase suffers from three problems:
ModelResource.scalarepeats 31 of the 32 endpoints ofDatasetResource.scala, and the access rules are implemented three times: for workflows, for datasets and models, and for computing units. The database repeats itself in the same way: 17 of its 42 tables are per-kind copies.Proposal: Unify the Resource Management
I propose to unify resource management. By unify I mean: designing and implementing common primitives that are shared across all kinds of resources.
Based on current Texera's position, I see three major primitives:
P1: Resource CRUD: every kind has an id, a name, and an owner, and every kind needs the same operations: create, list, read, update, and delete.
P2: Resource version CRUD: a workflow version, a dataset version, and a model version are the same concept, which is an immutable snapshot of a resource. The
dataset_versionandmodel_versiontables already have the same columns.P3: Resource access control: every kind needs the same decision, which is whether a user may read or write a resource. The four
*_user_accesstables already have the same three columns: the user, the resource, and the privilege.What stays specific to a kind is its own fields and actions, such as executing a workflow or uploading a file to a dataset. Once the common parts exist in one copy, a new kind defines only what is specific to it, and a feature built on the common parts works for every kind.
Implementation Proposal
I see at least two layers whose implementation needs to be refactored: the database schema layer and the API definition layer. Each layer needs its own detailed discussion, so below I only give my proposal for each.
Layer 1: Database Schema Layer
At this layer, my proposal is to store the common parts once, under two supertypes:
ResourceandResource Version.Before: each kind has its own tables for the common parts. Each kind keeps its own relationships to
User, tenownandaccessrelationships in total, and each versioned kind keeps its own version table.After: every kind is a subtype of
Resource, which has a singleaccessrelationship toUserwith the levels own, read, and write. Every version is a subtype ofResource Version, keyed by(rid, vno), so onelineagetable can link a version to the versions it was derived from. A new kind adds only its own fields underResource.Layer 2: API Definition Layer
My proposal at this layer is to give every kind the same endpoints for the three common parts. For each part, the table below lists the endpoints before and after. In the After column,
{kind}is the plural name of a kind, such asworkflowsordatasets,{rid}is the id of a resource,{vno}is the number of a version, and{uid}is the id of a user.Resource CRUD
Before, each kind spells the same operation in its own way, and some kinds lack an operation. After, every kind has the same five operations.
POST /workflow/create,POST /dataset/create,POST /model/create,POST /computing-unit/create,POST /pve/db,POST /warehousePOST /{kind}GET /workflow/list,GET /dataset/list,GET /model/list,GET /computing-unit,GET /pve/db,GET /warehouse/statusGET /{kind}GET /workflow/{wid},GET /dataset/{did},GET /model/{mid},GET /computing-unit/{cuid}; none for environments and warehousesGET /{kind}/{rid}POST /workflow/update/name,POST /dataset/update/name,POST /model/update/name,PUT /computing-unit/{cuid}/rename/{name},PUT /pve/db/{veid}; none for warehousesPATCH /{kind}/{rid}POST /workflow/delete,DELETE /dataset/{did},DELETE /model/{mid},DELETE /computing-unit/{cuid}/terminate,DELETE /pve/db/{veid},DELETE /warehouse/{whid}DELETE /{kind}/{rid}Resource Version CRUD
Before, workflow versions have their own root path and no endpoint to create one, because a version is made whenever a workflow is saved, while dataset and model versions put the operation in the path. After, every versioned kind has the same three operations. A version is numbered within its resource and immutable, so it has no update or delete.
POST /dataset/{did}/version/create,POST /model/{mid}/version/create; none for workflows, wherePOST /workflow/persistmakes a version as a side effectPOST /{kind}/{rid}/versionsGET /version/{wid},GET /dataset/{did}/version/list,GET /model/{mid}/version/listGET /{kind}/{rid}/versionsGET /version/{wid}/{vid},GET /dataset/{did}/version/{dvid}/rootFileNodes,GET /model/{mid}/version/{mvid}/rootFileNodesGET /{kind}/{rid}/versions/{vno}Resource Access Control
Before, the same sharing endpoints are defined four times, in three services. Environments and warehouses have none, and no endpoint checks access, so each service checks it in its own code. After, every kind is shared and checked in the same way.
GET /access/workflow/list/{wid}, plus a copy each for datasets, models, and computing unitsGET /{kind}/{rid}/accessPUT /access/workflow/grant/{wid}/{email}/{privilege}, plus the same three copiesPUT /{kind}/{rid}/access/{uid}DELETE /access/workflow/revoke/{wid}/{email}, plus the same three copiesDELETE /{kind}/{rid}/access/{uid}POST /access/evaluationAll reactions