Skip to content

Commit

Permalink
feat: [CDE-127]: read multi-table and multi query data in a single SQ…
Browse files Browse the repository at this point in the history
…L txn (harness#2193)

* feat: [CDE-127]: starting and stopping states.
* feat: [CDE-127]: read multi-table and multi query data in a single SQL txn
  • Loading branch information
n00bitax authored and Harness committed Jul 10, 2024
1 parent d577102 commit 6e525fc
Show file tree
Hide file tree
Showing 13 changed files with 268 additions and 160 deletions.
100 changes: 69 additions & 31 deletions app/api/controller/gitspace/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,45 +87,28 @@ func (c *Controller) startGitspace(ctx context.Context, config *types.GitspaceCo
savedGitspaceInstance, err := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, config.ID, config.SpaceID)
const resourceNotFoundErr = "Failed to find gitspace: resource not found"
if err != nil && err.Error() != resourceNotFoundErr { // TODO fix this
return nil, fmt.Errorf("failed to find gitspace with config ID : %s %w", config.Identifier, err)
return nil, fmt.Errorf("failed to find gitspace instance for config ID : %s %w", config.Identifier, err)
}
config.GitspaceInstance = savedGitspaceInstance
_, err = c.gitspaceBusyOperation(ctx, config)
if err != nil {
return nil, err
}
if savedGitspaceInstance == nil || savedGitspaceInstance.State.IsFinalStatus() {
codeServerPassword := defaultAccessKey
gitspaceMachineUser := defaultMachineUser
now := time.Now().UnixMilli()
suffixUID, err := gonanoid.Generate(allowedUIDAlphabet, 6)
gitspaceInstance, err := c.createGitspaceInstance(config)
if err != nil {
return nil, fmt.Errorf("could not generate UID for gitspace config : %q %w", config.Identifier, err)
}
identifier := strings.ToLower(config.Identifier + "-" + suffixUID)
var gitspaceInstance = &types.GitspaceInstance{
GitSpaceConfigID: config.ID,
Identifier: identifier,
State: enum.GitspaceInstanceStateUninitialized,
UserID: config.UserID,
SpaceID: config.SpaceID,
SpacePath: config.SpacePath,
Created: now,
Updated: now,
TotalTimeUsed: 0,
}
if config.IDE == enum.IDETypeVSCodeWeb || config.IDE == enum.IDETypeVSCode {
gitspaceInstance.AccessKey = &codeServerPassword
gitspaceInstance.AccessType = enum.GitspaceAccessTypeUserCredentials
gitspaceInstance.MachineUser = &gitspaceMachineUser
return nil, err
}
if err = c.gitspaceInstanceStore.Create(ctx, gitspaceInstance); err != nil {
return nil, fmt.Errorf("failed to create gitspace instance for %s %w", config.Identifier, err)
}
newGitspaceInstance, err := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, config.ID, config.SpaceID)
newGitspaceInstance.SpacePath = config.SpacePath
if err != nil {
return nil, fmt.Errorf("failed to find gitspace with config ID : %s %w", config.Identifier, err)
}
config.GitspaceInstance = newGitspaceInstance
}

newGitspaceInstance, err := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, config.ID, config.SpaceID)
newGitspaceInstance.SpacePath = config.SpacePath
if err != nil {
return nil, fmt.Errorf("failed to find gitspace with config ID : %s %w", config.Identifier, err)
}
config.GitspaceInstance = newGitspaceInstance
updatedGitspace, err := c.orchestrator.StartGitspace(ctx, config)
if err != nil {
return nil, fmt.Errorf("failed to find start gitspace : %s %w", config.Identifier, err)
Expand All @@ -138,16 +121,71 @@ func (c *Controller) startGitspace(ctx context.Context, config *types.GitspaceCo
return config, nil
}

func (c *Controller) createGitspaceInstance(config *types.GitspaceConfig) (*types.GitspaceInstance, error) {
codeServerPassword := defaultAccessKey
gitspaceMachineUser := defaultMachineUser
now := time.Now().UnixMilli()
suffixUID, err := gonanoid.Generate(allowedUIDAlphabet, 6)
if err != nil {
return nil, fmt.Errorf("could not generate UID for gitspace config : %q %w", config.Identifier, err)
}
identifier := strings.ToLower(config.Identifier + "-" + suffixUID)
var gitspaceInstance = &types.GitspaceInstance{
GitSpaceConfigID: config.ID,
Identifier: identifier,
State: enum.GitspaceInstanceStateStarting,
UserID: config.UserID,
SpaceID: config.SpaceID,
SpacePath: config.SpacePath,
Created: now,
Updated: now,
TotalTimeUsed: 0,
}
if config.IDE == enum.IDETypeVSCodeWeb || config.IDE == enum.IDETypeVSCode {
gitspaceInstance.AccessKey = &codeServerPassword
gitspaceInstance.AccessType = enum.GitspaceAccessTypeUserCredentials
gitspaceInstance.MachineUser = &gitspaceMachineUser
}
return gitspaceInstance, nil
}

func (c *Controller) gitspaceBusyOperation(
ctx context.Context,
config *types.GitspaceConfig,
) (*types.GitspaceConfig, error) {
if config.GitspaceInstance == nil {
return config, nil
}
if config.GitspaceInstance.State.IsBusyStatus() &&
time.Since(time.UnixMilli(config.Updated)) <= (10*60*1000) {
return nil, fmt.Errorf("gitspace start/stop is already pending for : %q", config.Identifier)
} else if config.GitspaceInstance.State.IsBusyStatus() {
config.GitspaceInstance.State = enum.GitspaceInstanceStateError
if err := c.gitspaceInstanceStore.Update(ctx, config.GitspaceInstance); err != nil {
return nil, fmt.Errorf("failed to update gitspace config for %s %w", config.Identifier, err)
}
}
return config, nil
}

func (c *Controller) stopGitspace(ctx context.Context, config *types.GitspaceConfig) (*types.GitspaceConfig, error) {
savedGitspace, err := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, config.ID, config.SpaceID)
if err != nil {
return nil, fmt.Errorf("failed to find gitspace with config ID : %s %w", config.Identifier, err)
}
if savedGitspace.State.IsFinalStatus() {
return nil, fmt.Errorf(
"gitspace Instance cannot be stopped with ID %s %w", savedGitspace.Identifier, err)
"gitspace instance cannot be stopped with ID %s %w", savedGitspace.Identifier, err)
}
config.GitspaceInstance = savedGitspace
config, err = c.gitspaceBusyOperation(ctx, config)
if err != nil {
return nil, err
}
config.GitspaceInstance.State = enum.GitspaceInstanceStateStopping
if err = c.gitspaceInstanceStore.Update(ctx, config.GitspaceInstance); err != nil {
return nil, fmt.Errorf("failed to update gitspace config for stopping %s %w", config.Identifier, err)
}
if updatedGitspace, stopErr := c.orchestrator.StopGitspace(ctx, config); stopErr != nil {
return nil, fmt.Errorf(
"failed to stop gitspace instance with ID %s %w", savedGitspace.Identifier, stopErr)
Expand Down
4 changes: 4 additions & 0 deletions app/api/controller/gitspace/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
gitspaceevents "github.com/harness/gitness/app/events/gitspace"
"github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/store/database/dbtx"
)

type Controller struct {
Expand All @@ -30,9 +31,11 @@ type Controller struct {
eventReporter *gitspaceevents.Reporter
orchestrator orchestrator.Orchestrator
gitspaceEventStore store.GitspaceEventStore
tx dbtx.Transactor
}

func NewController(
tx dbtx.Transactor,
authorizer authz.Authorizer,
infraProviderResourceStore store.InfraProviderResourceStore,
gitspaceConfigStore store.GitspaceConfigStore,
Expand All @@ -43,6 +46,7 @@ func NewController(
gitspaceEventStore store.GitspaceEventStore,
) *Controller {
return &Controller{
tx: tx,
authorizer: authorizer,
infraProviderResourceStore: infraProviderResourceStore,
gitspaceConfigStore: gitspaceConfigStore,
Expand Down
59 changes: 33 additions & 26 deletions app/api/controller/gitspace/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,33 +80,40 @@ func (c *Controller) Create(
return nil, fmt.Errorf("invalid input: %w", err)
}
now := time.Now().UnixMilli()
infraProviderResource, err := c.infraProviderResourceStore.FindByIdentifier(
ctx,
parentSpace.ID,
in.ResourceIdentifier)
var gitspaceConfig *types.GitspaceConfig
err = c.tx.WithTx(ctx, func(ctx context.Context) error {
infraProviderResource, err := c.infraProviderResourceStore.FindByIdentifier(
ctx,
parentSpace.ID,
in.ResourceIdentifier)
if err != nil {
return fmt.Errorf("could not find infra provider resource : %q %w", in.ResourceIdentifier, err)
}
gitspaceConfig = &types.GitspaceConfig{
Identifier: identifier,
Name: in.Name,
IDE: in.IDE,
InfraProviderResourceID: infraProviderResource.ID,
InfraProviderResourceIdentifier: infraProviderResource.Identifier,
CodeRepoType: enum.CodeRepoTypeUnknown, // TODO fix this
State: enum.GitspaceStateUninitialized,
CodeRepoURL: in.CodeRepoURL,
Branch: in.Branch,
DevcontainerPath: in.DevcontainerPath,
UserID: session.Principal.UID,
SpaceID: parentSpace.ID,
SpacePath: parentSpace.Path,
Created: now,
Updated: now,
}
err = c.gitspaceConfigStore.Create(ctx, gitspaceConfig)
if err != nil {
return fmt.Errorf("failed to create gitspace config for : %q %w", identifier, err)
}
return nil
})
if err != nil {
return nil, fmt.Errorf("could not find infra provider resource : %q %w", in.ResourceIdentifier, err)
}
gitspaceConfig := &types.GitspaceConfig{
Identifier: identifier,
Name: in.Name,
IDE: in.IDE,
InfraProviderResourceID: infraProviderResource.ID,
InfraProviderResourceIdentifier: infraProviderResource.Identifier,
CodeRepoType: enum.CodeRepoTypeUnknown, // TODO fix this
State: enum.GitspaceStateUninitialized,
CodeRepoURL: in.CodeRepoURL,
Branch: in.Branch,
DevcontainerPath: in.DevcontainerPath,
UserID: session.Principal.UID,
SpaceID: parentSpace.ID,
SpacePath: parentSpace.Path,
Created: now,
Updated: now,
}
err = c.gitspaceConfigStore.Create(ctx, gitspaceConfig)
if err != nil {
return nil, fmt.Errorf("failed to create gitspace config for : %q %w", identifier, err)
return nil, err
}
return gitspaceConfig, nil
}
Expand Down
4 changes: 1 addition & 3 deletions app/api/controller/gitspace/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package gitspace
import (
"context"
"fmt"
"strconv"

apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/auth"
Expand Down Expand Up @@ -58,8 +57,7 @@ func (c *Controller) Delete(
}
gitspaceConfig.IsDeleted = true
if err = c.gitspaceConfigStore.Update(ctx, gitspaceConfig); err != nil {
log.Err(err).Msg("Failed to delete gitspace config with ID " + strconv.FormatInt(gitspaceConfig.ID, 10))
return err
return fmt.Errorf("failed to delete gitspace config with ID: %s %w", gitspaceConfig.Identifier, err)
}
return nil
}
Expand Down
52 changes: 32 additions & 20 deletions app/api/controller/gitspace/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,35 +31,47 @@ func (c *Controller) Find(
identifier string,
) (*types.GitspaceConfig, error) {
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
const resourceNotFoundErr = "Failed to find gitspace: resource not found"
if err != nil {
return nil, fmt.Errorf("failed to find space: %w", err)
}
err = apiauth.CheckGitspace(ctx, c.authorizer, session, space.Path, identifier, enum.PermissionGitspaceView)
if err != nil {
return nil, fmt.Errorf("failed to authorize: %w", err)
}
gitspaceConfig, err := c.gitspaceConfigStore.FindByIdentifier(ctx, space.ID, identifier)
if err != nil {
return nil, fmt.Errorf("failed to find gitspace config: %w", err)
}
infraProviderResource, err := c.infraProviderResourceStore.Find(
ctx,
gitspaceConfig.InfraProviderResourceID)
if err != nil {
return nil, fmt.Errorf("failed to find infra provider resource for gitspace config: %w", err)
}
gitspaceConfig.SpacePath = space.Path
gitspaceConfig.InfraProviderResourceIdentifier = infraProviderResource.Identifier
instance, _ := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, gitspaceConfig.ID, gitspaceConfig.SpaceID)
if instance != nil {
gitspaceConfig.GitspaceInstance = instance
gitspaceStateType, err := enum.GetGitspaceStateFromInstance(instance.State)
var gitspaceConfig *types.GitspaceConfig
err = c.tx.WithTx(ctx, func(ctx context.Context) error {
gitspaceConfig, err = c.gitspaceConfigStore.FindByIdentifier(ctx, space.ID, identifier)
if err != nil {
return nil, err
return fmt.Errorf("failed to find gitspace config: %w", err)
}
gitspaceConfig.State = gitspaceStateType
} else {
gitspaceConfig.State = enum.GitspaceStateUninitialized
infraProviderResource, err := c.infraProviderResourceStore.Find(
ctx,
gitspaceConfig.InfraProviderResourceID)
if err != nil {
return fmt.Errorf("failed to find infra provider resource for gitspace config: %w", err)
}
gitspaceConfig.SpacePath = space.Path
gitspaceConfig.InfraProviderResourceIdentifier = infraProviderResource.Identifier
instance, err := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, gitspaceConfig.ID, gitspaceConfig.SpaceID)
if err != nil && err.Error() != resourceNotFoundErr { // TODO fix this
return fmt.Errorf("failed to find gitspace instance for config ID : %s %w", gitspaceConfig.Identifier, err)
}
if instance != nil {
gitspaceConfig.GitspaceInstance = instance
instance.SpacePath = gitspaceConfig.SpacePath
gitspaceStateType, err := enum.GetGitspaceStateFromInstance(instance.State)
if err != nil {
return err
}
gitspaceConfig.State = gitspaceStateType
} else {
gitspaceConfig.State = enum.GitspaceStateUninitialized
}
return nil
})
if err != nil {
return nil, err
}
return gitspaceConfig, nil
}
3 changes: 3 additions & 0 deletions app/api/controller/gitspace/wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
gitspaceevents "github.com/harness/gitness/app/events/gitspace"
"github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/store/database/dbtx"

"github.com/google/wire"
)
Expand All @@ -29,6 +30,7 @@ var WireSet = wire.NewSet(
)

func ProvideController(
tx dbtx.Transactor,
authorizer authz.Authorizer,
resourceStore store.InfraProviderResourceStore,
configStore store.GitspaceConfigStore,
Expand All @@ -39,6 +41,7 @@ func ProvideController(
eventStore store.GitspaceEventStore,
) *Controller {
return NewController(
tx,
authorizer,
resourceStore,
configStore,
Expand Down
4 changes: 4 additions & 0 deletions app/api/controller/infraprovider/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/harness/gitness/app/auth/authz"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/store/database/dbtx"
)

type Controller struct {
Expand All @@ -26,16 +27,19 @@ type Controller struct {
infraProviderConfigStore store.InfraProviderConfigStore
infraProviderFactory infraprovider.Factory
spaceStore store.SpaceStore
tx dbtx.Transactor
}

func NewController(
tx dbtx.Transactor,
authorizer authz.Authorizer,
infraProviderResourceStore store.InfraProviderResourceStore,
infraProviderConfigStore store.InfraProviderConfigStore,
factory infraprovider.Factory,
spaceStore store.SpaceStore,
) *Controller {
return &Controller{
tx: tx,
authorizer: authorizer,
infraProviderResourceStore: infraProviderResourceStore,
infraProviderConfigStore: infraProviderConfigStore,
Expand Down
Loading

0 comments on commit 6e525fc

Please sign in to comment.