Files
ipcr-forge/forge/queue.go
T
Worph 6fe4c40cbe IPCR Forge v3: Gitea as the source of truth, public repos mirrored to Radicle
Users found Radicle-as-source unfriendly (v1, v2). Gitea is now where
people work; its Actions build images into the staging registry IPCR
follows, as in v2.

- bridge/: ipcr-forge-bridge (Go). Install step mints a public-only
  token, registers one system webhook and creates the ipcr-hello example;
  the service mirrors every public repo one way to Radicle (rad init,
  canonical tags rule, git push rad) and serves the forge's page.
- Compose: gitea + act_runner on a separate dind; tile opens Gitea;
  tips link the forge page.
- Removed the Radicle CI broker (ci/) and the nginx landing page.
2026-10-04 18:34:26 +00:00

55 lines
1.0 KiB
Go

package main
import "sync"
// queue holds the repositories waiting for a sync, each at most once, served by one worker: a
// burst of webhooks for one repository costs one sync, and two syncs never race on a mirror or on
// the node's storage.
type queue struct {
mu sync.Mutex
order []int64
pending map[int64]bool
wake chan struct{}
}
func newQueue() *queue {
return &queue{pending: map[int64]bool{}, wake: make(chan struct{}, 1)}
}
func (q *queue) add(id int64) {
q.mu.Lock()
if !q.pending[id] {
q.pending[id] = true
q.order = append(q.order, id)
}
q.mu.Unlock()
select {
case q.wake <- struct{}{}:
default:
}
}
// next pops the oldest repository, or reports false when the queue is empty.
func (q *queue) next() (int64, bool) {
q.mu.Lock()
defer q.mu.Unlock()
if len(q.order) == 0 {
return 0, false
}
id := q.order[0]
q.order = q.order[1:]
delete(q.pending, id)
return id, true
}
func (q *queue) run(work func(id int64)) {
for {
id, ok := q.next()
if !ok {
<-q.wake
continue
}
work(id)
}
}