GitRoot
Craft your forge, Build your project, Grow your community freely
1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
2//
3// SPDX-License-Identifier: EUPL-1.2
4
5package repository
6
7import (
8 "sync"
9
10 "gitroot.dev/server/logger"
11)
12
13type repoLocks struct {
14 logger *logger.Logger
15 locks map[string]*repoLock
16 lock sync.Mutex
17}
18
19type repoLock struct {
20 repoName string
21 logger *logger.Logger
22 willWrite sync.Mutex
23 write sync.RWMutex
24}
25
26func newRepoLocks() *repoLocks {
27 return &repoLocks{
28 logger: logger.NewLogger(logger.REPOSITORY_LOCK),
29 locks: make(map[string]*repoLock),
30 lock: sync.Mutex{},
31 }
32}
33
34func (rl *repoLocks) get(repoName string) *repoLock {
35 rl.lock.Lock()
36 defer rl.lock.Unlock()
37 _, ok := rl.locks[repoName]
38 if !ok {
39 rl.locks[repoName] = &repoLock{
40 repoName: repoName,
41 logger: rl.logger,
42 willWrite: sync.Mutex{},
43 write: sync.RWMutex{},
44 }
45 }
46 return rl.locks[repoName]
47}
48
49func (rl *repoLocks) Read(repoName string) func() {
50 rl.logger.Debug("ReadLock", logger.NewLoggerPair("repoName", repoName))
51 l := rl.get(repoName)
52 l.write.RLock()
53 return func() {
54 rl.logger.Debug("ReadUnlock", logger.NewLoggerPair("repoName", repoName))
55 l.write.RUnlock()
56 }
57}
58
59func (rl *repoLocks) WillWrite(repoName string) *repoLock {
60 l := rl.get(repoName)
61 rl.logger.Debug("WillWrite", logger.NewLoggerPair("repoName", repoName))
62 l.willWrite.Lock()
63 return l
64}
65
66func (l *repoLock) Close() {
67 l.logger.Debug("WillWrite close", logger.NewLoggerPair("repoName", l.repoName))
68 l.willWrite.Unlock()
69}
70
71func (l *repoLock) Write() func() {
72 l.logger.Debug("WriteLock", logger.NewLoggerPair("repoName", l.repoName))
73 l.write.Lock()
74 return func() {
75 l.logger.Debug("WriteUnlock", logger.NewLoggerPair("repoName", l.repoName))
76 l.write.Unlock()
77 }
78}