Skip to content

Commit

Permalink
syncronize keyspace creation
Browse files Browse the repository at this point in the history
  • Loading branch information
phact committed Sep 16, 2021
1 parent d9cd79d commit 8b47871
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
51 changes: 51 additions & 0 deletions internal/provider/mutex-helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package provider

import (
"log"
"sync"
)

// MutexKV is a simple key/value store for arbitrary mutexes. It can be used to
// serialize changes across arbitrary collaborators that share knowledge of the
// keys they must serialize on.
//
// The initial use case is to let aws_security_group_rule resources serialize
// their access to individual security groups based on SG ID.
type MutexKV struct {
lock sync.Mutex
store map[string]*sync.Mutex
}

// Locks the mutex for the given key. Caller is responsible for calling Unlock
// for the same key
func (m *MutexKV) Lock(key string) {
log.Printf("[DEBUG] Locking %q", key)
m.get(key).Lock()
log.Printf("[DEBUG] Locked %q", key)
}

// Unlock the mutex for the given key. Caller must have called Lock for the same key first
func (m *MutexKV) Unlock(key string) {
log.Printf("[DEBUG] Unlocking %q", key)
m.get(key).Unlock()
log.Printf("[DEBUG] Unlocked %q", key)
}

// Returns a mutex for the given key, no guarantee of its lock status
func (m *MutexKV) get(key string) *sync.Mutex {
m.lock.Lock()
defer m.lock.Unlock()
mutex, ok := m.store[key]
if !ok {
mutex = &sync.Mutex{}
m.store[key] = mutex
}
return mutex
}

// Returns a properly initialized MutexKV
func NewMutexKV() *MutexKV {
return &MutexKV{
store: make(map[string]*sync.Mutex),
}
}
3 changes: 3 additions & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ func New(version string) func() *schema.Provider {
}
}

// This is a global MutexKV for use within this plugin.
var astraMutexKV = NewMutexKV()

func configure(providerVersion string, p *schema.Provider) func(context.Context, *schema.ResourceData) (interface{}, diag.Diagnostics) {
return func(_ context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
userAgent := p.UserAgent("terraform-provider-astra", providerVersion)
Expand Down
3 changes: 3 additions & 0 deletions internal/provider/resource_keyspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ func resourceKeyspaceCreate(ctx context.Context, d *schema.ResourceData, meta in
databaseID := d.Get("database_id").(string)
keyspaceName := d.Get("name").(string)

astraMutexKV.Lock(databaseID)
defer astraMutexKV.Unlock(databaseID)

//Wait for DB to be in Active status
if err := resource.RetryContext(ctx, d.Timeout(schema.TimeoutCreate), func() *resource.RetryError {
res, err := client.GetDatabaseWithResponse(ctx, astra.DatabaseIdParam(databaseID))
Expand Down

0 comments on commit 8b47871

Please sign in to comment.