diff options
Diffstat (limited to 'internal/db')
-rw-r--r-- | internal/db/actions.go | 8 | ||||
-rw-r--r-- | internal/db/postgres.go | 24 |
2 files changed, 28 insertions, 4 deletions
diff --git a/internal/db/actions.go b/internal/db/actions.go index 9a3012465..6fa7d23ae 100644 --- a/internal/db/actions.go +++ b/internal/db/actions.go @@ -29,8 +29,8 @@ import ( // Initialize will initialize the database given in the config for use with GoToSocial var Initialize action.GTSAction = func(ctx context.Context, c *config.Config, log *logrus.Logger) error { db, err := New(ctx, c, log) - if err != nil { - return err - } - return db.CreateSchema(ctx) + if err != nil { + return err + } + return db.CreateSchema(ctx) } diff --git a/internal/db/postgres.go b/internal/db/postgres.go index 5a23b8121..3c7af4522 100644 --- a/internal/db/postgres.go +++ b/internal/db/postgres.go @@ -25,6 +25,7 @@ import ( "net/url" "regexp" "strings" + "sync" "time" "github.com/go-fed/activity/streams/vocab" @@ -41,6 +42,7 @@ type postgresService struct { conn *pg.DB log *logrus.Entry cancel context.CancelFunc + locks *sync.Map } // newPostgresService returns a postgresService derived from the provided config, which implements the go-fed DB interface. @@ -109,6 +111,7 @@ func newPostgresService(ctx context.Context, c *config.Config, log *logrus.Entry conn: conn, log: log, cancel: cancel, + locks: &sync.Map{}, }, nil } @@ -171,10 +174,31 @@ func derivePGOptions(c *config.Config) (*pg.Options, error) { GO-FED DB INTERFACE-IMPLEMENTING FUNCTIONS */ func (ps *postgresService) Lock(ctx context.Context, id *url.URL) error { + // Before any other Database methods are called, the relevant `id` + // entries are locked to allow for fine-grained concurrency. + + // Strategy: create a new lock, if stored, continue. Otherwise, lock the + // existing mutex. + mu := &sync.Mutex{} + mu.Lock() // Optimistically lock if we do store it. + i, loaded := ps.locks.LoadOrStore(id.String(), mu) + if loaded { + mu = i.(*sync.Mutex) + mu.Lock() + } return nil } func (ps *postgresService) Unlock(ctx context.Context, id *url.URL) error { + // Once Go-Fed is done calling Database methods, the relevant `id` + // entries are unlocked. + + i, ok := ps.locks.Load(id.String()) + if !ok { + return errors.New("missing an id in unlock") + } + mu := i.(*sync.Mutex) + mu.Unlock() return nil } |