Skip to content

View field create many mutation#15576

Merged
Weiko merged 13 commits intomainfrom
view-field-create-many
Nov 4, 2025
Merged

View field create many mutation#15576
Weiko merged 13 commits intomainfrom
view-field-create-many

Conversation

@prastoin
Copy link
Copy Markdown
Contributor

@prastoin prastoin commented Nov 3, 2025

Introduction

When creating a view with v2 flag activated in production result in race condition due to request being slow and //.
That's why we're introducing a batch create on view field here
closing twentyhq/core-team-issues#1836

In v2

  • batch create view field endpoint is available
  • frontend will target the new endpoint

In v1

  • batch create view field endpoint is not available
  • frontend will stick to old fake batch view field creation loop

Polish

  • use persist view field is quite verbose as contains two data model we could aim to create an update many view fields in order to standardize new pattern

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Nov 3, 2025

🚀 Preview Environment Ready!

Your preview environment is available at: http://bore.pub:64319

This environment will automatically shut down when the PR is closed or after 5 hours.

@prastoin prastoin self-assigned this Nov 3, 2025
@prastoin prastoin marked this pull request as ready for review November 3, 2025 17:33
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Greptile Overview

Greptile Summary

This PR introduces a batch creation endpoint for view fields to solve race condition issues when creating views with multiple fields in production with the v2 flag enabled.

Key Changes

  • Backend: Added createManyCoreViewFields mutation in the resolver that only works when IS_WORKSPACE_MIGRATION_V2_ENABLED feature flag is active
  • Backend Service: Refactored ViewFieldV2Service.createOne to internally use the new createMany method, implementing proper batch processing with validation
  • Frontend: Updated usePersistViewField hook to use the batch mutation in v2 while maintaining backward compatibility with v1 through oldCreateViewFields
  • Frontend Usage: Updated useSaveCurrentViewFields and useCreateViewFromCurrentView to use the new { inputs: [...] } signature
  • Tests: Added comprehensive test coverage for both successful and failing scenarios, including edge case of empty input arrays

Implementation Approach

The solution implements a progressive enhancement pattern:

  • In v1 (flag disabled): Frontend continues to use sequential individual mutations via oldCreateViewFields
  • In v2 (flag enabled): Frontend uses the new batch endpoint, backend processes all fields in a single transaction

This eliminates race conditions by ensuring all view fields are created atomically in a single database transaction when using v2.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The implementation is well-structured with proper feature flag gating, maintains backward compatibility with v1, includes comprehensive test coverage for both success and error cases, and follows established patterns in the codebase. The refactoring of createOne to use createMany internally is a clean approach that reduces code duplication.
  • No files require special attention

Important Files Changed

File Analysis

Filename Score Overview
packages/twenty-server/src/engine/metadata-modules/view-field/resolvers/view-field.resolver.ts 5/5 Adds createManyCoreViewFields mutation with proper feature flag check; delegates to v2 service correctly
packages/twenty-server/src/engine/metadata-modules/view-field/services/view-field-v2.service.ts 5/5 Refactored createOne to use createMany, adds proper batch creation logic with validation and error handling
packages/twenty-front/src/modules/views/hooks/internal/usePersistViewField.ts 5/5 Refactored to use batch mutation in v2, maintains backward compatibility with v1 using oldCreateViewFields
packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts 5/5 Updated to use new batch mutation signature with inputs wrapper object
packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts 5/5 Updated to use new batch mutation signature with inputs wrapper object

Sequence Diagram

sequenceDiagram
    participant Frontend as Frontend (usePersistViewField)
    participant Resolver as ViewFieldResolver
    participant FeatureFlag as FeatureFlagService
    participant V2Service as ViewFieldV2Service
    participant Cache as FlatEntityMapsCacheService
    participant Migration as MigrationValidateBuildAndRunService
    participant DB as Database

    Frontend->>Resolver: createManyCoreViewFields(inputs)
    Resolver->>FeatureFlag: isFeatureEnabled(IS_WORKSPACE_MIGRATION_V2_ENABLED)
    FeatureFlag-->>Resolver: enabled/disabled
    
    alt V2 Not Enabled
        Resolver-->>Frontend: throw ViewFieldException
    else V2 Enabled
        Resolver->>V2Service: createMany(createViewFieldInputs, workspaceId)
        
        alt Empty inputs
            V2Service-->>Resolver: return []
        else Has inputs
            V2Service->>Cache: getOrRecomputeManyOrAllFlatEntityMaps()
            Cache-->>V2Service: existing flat entity maps
            
            V2Service->>V2Service: transform inputs to flatViewFieldsToCreate
            V2Service->>V2Service: computeFlatEntityMapsFromTo()
            
            V2Service->>Migration: validateBuildAndRunWorkspaceMigration()
            Migration->>Migration: validate view fields
            Migration->>DB: run migration
            DB-->>Migration: success/error
            
            alt Validation errors
                Migration-->>V2Service: validation errors
                V2Service-->>Resolver: throw WorkspaceMigrationBuilderExceptionV2
                Resolver-->>Frontend: error
            else Success
                Migration-->>V2Service: success
                V2Service->>Cache: getOrRecomputeManyOrAllFlatEntityMaps()
                Cache-->>V2Service: recomputed maps with new entities
                V2Service->>V2Service: findManyFlatEntityByIdInFlatEntityMapsOrThrow()
                V2Service-->>Resolver: created ViewFieldDTOs[]
                Resolver-->>Frontend: created ViewFieldDTOs[]
                Frontend->>Frontend: triggerViewFieldOptimisticEffect()
            end
        end
    end
Loading

13 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@prastoin
Copy link
Copy Markdown
Contributor Author

prastoin commented Nov 3, 2025

Will update test tomorrow

@prastoin
Copy link
Copy Markdown
Contributor Author

prastoin commented Nov 4, 2025

Temporarily updated the coverage lines expectations in twenty front as added lines that aims to be removed after v2 activation

Copy link
Copy Markdown
Member

@Weiko Weiko left a comment

Choose a reason for hiding this comment

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

LGTM @prastoin FYI we should do the same with Kanban, I believe we run N createCoreViewGroup (@charlesBochet FYI)

@Weiko Weiko merged commit a3dc6e5 into main Nov 4, 2025
65 checks passed
@Weiko Weiko deleted the view-field-create-many branch November 4, 2025 10:36
@prastoin
Copy link
Copy Markdown
Contributor Author

prastoin commented Nov 4, 2025

Nice catch will create a dedicated PR

Weiko pushed a commit that referenced this pull request Nov 4, 2025
# Introduction
Same as #15576 but for view
groups creation

When creating a kanban view with v2 flag activated in production result
in race condition due to request being slow and //.
That's why we're introducing a batch create on view group here
closing twentyhq/core-team-issues#1847

## In v2
- batch create view group endpoint is available
- frontend will target the new endpoint

## In v1
- batch create view group endpoint is not available
- frontend will stick to old fake batch view group creation loop


## Gallery
### v2
<img width="1796" height="486" alt="image"
src="https://github.com/user-attachments/assets/932cfe9f-85f1-41cc-a1c4-72a4b5d5a256"
/>

### v1
<img width="1852" height="966" alt="image"
src="https://github.com/user-attachments/assets/8aa9df11-cdea-4b12-ae60-118cdf5e257b"
/>
@sentry
Copy link
Copy Markdown

sentry bot commented Nov 13, 2025

Issues attributed to commits in this pull request

This pull request was merged and Sentry observed the following issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants