// Copyright (c) 2022 Gitpod GmbH. All rights reserved. // Licensed under the GNU Affero General Public License (AGPL). // See License.AGPL.txt in the project root for license information. package db import ( "context" "database/sql" "fmt" "math" "time" "github.com/google/uuid" "gorm.io/datatypes" "gorm.io/gorm" ) // Workspace represents the underlying DB object type Workspace struct { ID string `gorm:"primary_key;column:id;type:char;size:36;" json:"id"` OrganizationId *uuid.UUID `gorm:"column:organizationId;type:char;size:36;" json:"organizationId"` OwnerID uuid.UUID `gorm:"column:ownerId;type:char;size:36;" json:"ownerId"` ProjectID sql.NullString `gorm:"column:projectId;type:char;size:36;" json:"projectId"` Description string `gorm:"column:description;type:varchar;size:255;" json:"description"` Type WorkspaceType `gorm:"column:type;type:char;size:16;default:regular;" json:"type"` CloneURL string `gorm:"column:cloneURL;type:varchar;size:255;" json:"cloneURL"` ContextURL string `gorm:"column:contextURL;type:text;size:65535;" json:"contextURL"` Context datatypes.JSON `gorm:"column:context;type:text;size:65535;" json:"context"` Config datatypes.JSON `gorm:"column:config;type:text;size:65535;" json:"config"` BasedOnPrebuildID sql.NullString `gorm:"column:basedOnPrebuildId;type:char;size:36;" json:"basedOnPrebuildId"` BasedOnSnapshotID sql.NullString `gorm:"column:basedOnSnapshotId;type:char;size:36;" json:"basedOnSnapshotId"` ImageSource datatypes.JSON `gorm:"column:imageSource;type:text;size:65535;" json:"imageSource"` ImageNameResolved string `gorm:"column:imageNameResolved;type:varchar;size:255;" json:"imageNameResolved"` BaseImageNameResolved string `gorm:"column:baseImageNameResolved;type:varchar;size:255;" json:"baseImageNameResolved"` CreationTime VarcharTime `gorm:"column:creationTime;type:varchar;size:255;" json:"creationTime"` LastModified time.Time `gorm:"column:_lastModified;type:timestamp;default:CURRENT_TIMESTAMP(6);" json:"_lastModified"` SoftDeletedTime VarcharTime `gorm:"column:softDeletedTime;type:varchar;size:255;" json:"softDeletedTime"` ContentDeletedTime VarcharTime `gorm:"column:contentDeletedTime;type:varchar;size:255;" json:"contentDeletedTime"` Archived bool `gorm:"column:archived;type:tinyint;default:0;" json:"archived"` Shareable bool `gorm:"column:shareable;type:tinyint;default:0;" json:"shareable"` SoftDeleted sql.NullString `gorm:"column:softDeleted;type:char;size:4;" json:"softDeleted"` Pinned bool `gorm:"column:pinned;type:tinyint;default:0;" json:"pinned"` // deleted is reserved for use by periodic deleter _ int32 `gorm:"column:deleted;type:tinyint;default:0;" json:"deleted"` } func (d *Workspace) TableName() string { return "d_b_workspace" } type WorkspaceType string const ( WorkspaceType_Prebuild WorkspaceType = "prebuild" WorkspaceType_Probe WorkspaceType = "probe" WorkspaceType_Regular WorkspaceType = "regular" ) const maxListBatchSize = 65535 // 2^16 - 1 func ListWorkspacesByID(ctx context.Context, conn *gorm.DB, ids []string) ([]Workspace, error) { if len(ids) == 0 { return nil, nil } var workspaces []Workspace items := len(ids) batches := int(math.Ceil(float64(items) / maxListBatchSize)) for i := 0; i < batches; i++ { lower := i * maxListBatchSize upper := (i + 1) * maxListBatchSize if upper > items { upper = items } batchIDs := ids[lower:upper] var results []Workspace tx := conn.WithContext(ctx).Where(batchIDs).Find(&results) if tx.Error != nil { return nil, fmt.Errorf("failed to list workspaces by id: %w", tx.Error) } workspaces = append(workspaces, results...) } return workspaces, nil }