feat: polish & windviz & deploy
This commit is contained in:
parent
81b8e763bd
commit
465ad00f7b
78 changed files with 20622 additions and 2154 deletions
50
internal/datasets/lock_unix.go
Normal file
50
internal/datasets/lock_unix.go
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//go:build unix
|
||||
|
||||
package datasets
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// lockPollInterval is how often a contended lock is retried. The lock is held
|
||||
// for the duration of a dataset download (minutes), so sub-second acquisition
|
||||
// latency is irrelevant.
|
||||
const lockPollInterval = 150 * time.Millisecond
|
||||
|
||||
// flockExclusive acquires an exclusive flock on path, creating the lock file
|
||||
// if needed, and blocks until it is held or ctx is cancelled.
|
||||
//
|
||||
// It uses non-blocking LOCK_NB attempts in a poll loop rather than a blocking
|
||||
// flock in a goroutine: the file descriptor is only ever touched by this
|
||||
// goroutine, so there is no race between a pending syscall and Close on
|
||||
// cancellation.
|
||||
func flockExclusive(ctx context.Context, path string) (func(), error) {
|
||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0o644)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open lock file: %w", err)
|
||||
}
|
||||
for {
|
||||
err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
|
||||
if err == nil {
|
||||
return func() {
|
||||
_ = syscall.Flock(int(f.Fd()), syscall.LOCK_UN)
|
||||
_ = f.Close()
|
||||
}, nil
|
||||
}
|
||||
if !errors.Is(err, syscall.EWOULDBLOCK) {
|
||||
f.Close()
|
||||
return nil, fmt.Errorf("flock: %w", err)
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
f.Close()
|
||||
return nil, ctx.Err()
|
||||
case <-time.After(lockPollInterval):
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue