Skip to content

View Operations ​

End-to-end flows for view CREATE, UPDATE, DELETE, and schema sync/reset. Views map to database tables in the customer database — creating or deleting a view means creating or dropping an actual table.

View CREATE ​

Creates a new view (table) — always asynchronous because it requires CREATE TABLE on the customer database.

Response: 202 Accepted

Frontend (App)                  Quarkus REST                         RabbitMQ              Processor (Spring Boot)
─────────────────                  ────────────                         ────────              ───────────────────────
User clicks "Add View"
    │
    ▼
NgRx action: createView
    │
    ▼
ViewCrudEffects
    │ POST /api/metadata/views
    ▼
ViewResource.createView()
    │
    ▼
ViewService
  .createByWorkspaceUuid()
    │
    ├── Generates EntityMetadataDTO
    │   (no View entity yet —
    │    processor creates it)
    │
    └── Queues outbox message
                                                                          │
                                                              MetadataUpdateProducer
                                                            .onEntityChange(CREATE)
                                                                          │
                                                                          ▼
                                                                  metadata-updates
                                                                     exchange
                                                                          │
                                                                          ▼
                                                              EntityMetadataConsumer
                                                            .processEntityMetadataInternal()
                                                                          │
                                                                          ▼
                                                              CREATE TABLE IF NOT EXISTS
                                                              (via FlywayMigrationService)
                                                                          │
                                                                          ▼
                                                              TaskCompletionProducer
                                                                .sendSuccess()
                                                                          │
                                                                          ▼
                                                                  task-completion
                                                                     exchange
    ┌─────────────────────────────────────────────────────────────────────┘
    ▼
Quarkus TaskCompletionConsumer
    │
    ▼
ViewOperationHandler
  .handleCreate()
    │
    ├── Creates View entity
    ├── Creates all ViewColumns
    └── Creates ColumnMetadata records
    │
    ▼
SSE: workspace.view.created
    │
    ▼
Frontend receives SSE
    │
    ▼
NgRx action: viewCreatedFromSSE
    │
    ▼
Navigate to new view

Key Detail: Deferred View Entity Creation ​

Unlike columns (where metadata is created before the processor runs), views are only created in the metadata DB after the processor succeeds. The flow:

  1. REST endpoint generates an EntityMetadataDTO describing the table structure
  2. This DTO is sent to the processor via RabbitMQ (no View entity exists yet)
  3. Processor creates the physical table
  4. On success, ViewOperationHandler.handleCreate() creates the View, ViewColumn, and ColumnMetadata records

This means if the processor fails, no orphan View record exists in the metadata DB.

Frontend Optimistic Create ​

  • A temporary view is added to the sidebar immediately with a generated UUID
  • The view shows a loading state until SSE confirms creation
  • A timeout mechanism removes the temp view if no SSE confirmation arrives within a configured window
  • On SSE workspace.view.created: the temp view is replaced with the real view and the user is navigated to it

View DELETE ​

Deletes a view (drops the table) — asynchronous with optimistic archival.

Response: 202 Accepted

Frontend (App)                  Quarkus REST                         RabbitMQ              Processor (Spring Boot)
─────────────────                  ────────────                         ────────              ───────────────────────
User deletes view
(confirm dialog)
    │
    ▼
NgRx action: deleteView
    │
    ▼
ViewCrudEffects
    │ DELETE /api/metadata/
    │   views/{uuid}
    ▼
ViewResource.deleteView()
    │
    ▼
ViewService
  .deleteByUuid()
    │
    ├── Archives the view
    │   (soft delete)
    │
    └── Queues outbox message
                                                                          │
                                                              MetadataUpdateProducer
                                                            .onEntityChange(DELETE)
                                                                          │
                                                                          ▼
                                                                  metadata-updates
                                                                     exchange
                                                                          │
                                                                          ▼
                                                              EntityMetadataConsumer
                                                            .processEntityMetadataInternal()
                                                                          │
                                                                          ▼
                                                              DROP TABLE IF EXISTS
                                                              (via FlywayMigrationService)
                                                                          │
                                                                          ▼
                                                              TaskCompletionProducer
                                                                .sendSuccess()
                                                                          │
                                                                          ▼
                                                                  task-completion
                                                                     exchange
    ┌─────────────────────────────────────────────────────────────────────┘
    ▼
Quarkus TaskCompletionConsumer
    │
    ▼
ViewOperationHandler
  .handleDelete()
    │
    ├── Cascade delete ViewColumns
    ├── Cascade delete ColumnMetadata
    └── Delete View entity
    │
    ▼
SSE: workspace.view.deleted
    │
    ▼
Frontend: viewDeletedFromSSE
    │
    ▼
Remove view from sidebar,
navigate to next view

Archive-First Strategy ​

The view is archived (soft-deleted) before the processor runs. This allows rollback:

  • On success: ViewOperationHandler.handleDelete() performs the hard delete of all related records
  • On failure: the view is unarchived (restored) and an error notification is shown to the user

Cascade Delete Order ​

ViewOperationHandler.handleDelete() cleans up in this order:

  1. ViewColumnPath records
  2. ViewColumn records
  3. ColumnMetadata records
  4. View entity itself

View UPDATE ​

Updates view properties (name, slug, position) — synchronous, no processor involvement.

Response: 200 OK

Frontend (App)                  Quarkus REST
─────────────────                  ────────────
User renames view
or changes position
    │
    ▼
NgRx action: updateView
    │
    ▼
ViewCrudEffects
    │ PUT /api/metadata/views/{uuid}
    ▼
ViewResource.updateView()
    │
    ▼
ViewService.updateByUuid()
    │
    ├── Updates View entity
    │   (name, slug, position)
    │
    └── Returns updated view
    │
    ▼
SSE: workspace.view.updated
    │
    ▼
Other clients: viewUpdatedFromSSE

View updates are simple because they only affect metadata — no table structure changes, no processor involvement.


Schema Sync / Reset ​

Re-synchronizes the metadata DB with the actual state of the customer database. Used when a customer modifies their database directly (outside SchemaStack) and needs the UI to reflect the changes.

Frontend (Admin)                   Quarkus REST
─────────────────                  ────────────
User clicks "Sync Schema"
    │
    ▼
POST /api/workspace/
  {uuid}/schema/sync
    │
    ▼
SchemaResetService
  .resetSingleView()
    │
    ├── 1. Connect to customer DB
    │      (decrypt credentials,
    │       JDBC connection)
    │
    ├── 2. Introspect actual schema
    │      (DatabaseMetaData.getTables()
    │       + getColumns())
    │
    ├── 3. Compare with metadata
    │      (detect added/removed/
    │       changed columns)
    │
    ├── 4. Create new ViewColumns
    │      for added columns
    │
    ├── 5. Update changed columns
    │      (type mismatches, etc.)
    │
    └── 6. Remove ViewColumns for
          dropped columns
    │
    ▼
SSE: workspace notification
    │
    ▼
Frontend: reload view

SchemaSyncOrchestrator ​

The full workspace-level sync uses the SchemaSyncOrchestrator which manages a state machine with checkpoint/resume:

INITIATED → SCHEMA_EXTRACTED → ENTITIES_MERGED → RELATIONSHIPS_MERGED
    → VIEW_COLUMNS_GENERATED → HASH_UPDATED → COMPLETED

Each step is checkpointed so that a failed sync can be resumed from the last successful step rather than starting over.

Cross-reference

See the Multi-Tenancy page for full details on the SchemaSyncOrchestrator state machine, progress tracking, and the schema import flow.

What Sync Does NOT Do ​

  • Does not create or drop tables — only syncs column-level changes within existing views
  • Does not go through the processor — reads the customer DB directly via JDBC
  • Does not modify the customer database — it only updates SchemaStack's metadata to match reality

Response Code Summary ​

OperationSync/AsyncSuccess CodeNotes
View CREATEAsync202 AcceptedRequires CREATE TABLE
View DELETEAsync202 AcceptedRequires DROP TABLE
View UPDATESync200 OKMetadata only
Schema SyncSync200 OKDirect DB introspection

Cross-References ​

SchemaStack Internal Developer Documentation