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}