🌧 BitTorrent client and library in Go

rain

BitTorrent client and library in Go. Running in production at put.io.

Build Status GoDoc GitHub Release Go Report Card

Features

Screenshot

Rain Screenshot

Installing

If you are on MacOS you can install from brew:

brew install cenkalti/rain/rain

Otherwise, get the latest binary from releases page.

Usage as torrent client

Rain is distributed as single binary file. The main use case is running rain server command and operating the server with rain client <subcommand> commands. Server consists of a BitTorrent client and a RPC server. rain client is used to give commands to the server. There is also rain client console command which opens up a text based UI that you can view and manage the torrents on the server. Run rain help to see other commands.

Usage as library

// Create a session
ses, _ := torrent.NewSession(torrent.DefaultConfig)

// Add magnet link
tor, _ := ses.AddURI(magnetLink, nil)

// Watch the progress
for range time.Tick(time.Second) {
	s := tor.Stats()
	log.Printf("Status: %s, Downloaded: %d, Peers: %d", s.Status.String(), s.Bytes.Completed, s.Peers.Total)
}

More complete example can be found under handleDownload function at main.go file.

See package documentation for complete API.

Configuration

All values have sensible defaults, so you can run Rain with an empty config but if you want to customize it's behavior, you can pass a YAML config with -config flag. Config keys must be in lowercase. See the description of values in here: config.go

Difference from other clients

Rain is the main BitTorrent client used at put.io. It is designed to handle hundreds of torrents while using low system resources. The main difference from other clients is that Rain uses a separate peer port for each torrent. This allows Rain to download same torrent for multiple accounts in same private tracker and keep reporting their ratio correctly.

Missing features

Comments
  • How do I specify multiple files in different locations?

    How do I specify multiple files in different locations?

    Hello, trying to use the tool and I can't seem to find how to specify a list of files in different locations to be a part of the torrent. It seems I can specify a single file or a directory. However, I have files in different locations that I need to be a part of a single torrent.

  • torrent_start.go:116 cannot listen port error

    torrent_start.go:116 cannot listen port error

    2022-01-04 17:47:38 INFO     [torrent aJEicW2GEey_XQIACh5hCg] session_add.go:284 added torrent
    2022-01-04 17:47:38 INFO     [torrent aJEicW2GEey_XQIACh5hCg] torrent_start.go:31 starting torrent
    2022-01-04 17:47:38 WARNING  [torrent aJEicW2GEey_XQIACh5hCg] torrent_start.go:116 cannot listen port 53678: listen tcp4 :53678: bind: address already in use
    

    I get those errors randomly (in my tests but probably in real envs too). Since it's a warning session_add does not fail so I cannot handle the error easily. I have pre-existing code to give up / cancel a download after a certain amount of time, maybe I could use that and fail my test with a more visible error.

    Thanks for any thoughts on this. There is also something in go now to be able to double 'bind' on a port, but I don't think we want this. (so_reuse_port).

  • Saving to memory instead of disk

    Saving to memory instead of disk

    Hi there,

    How could the library be extended so that we just download the torrent but don't write it to disk, but to a memory buffer instead ?

    Would the idea be to make a 'memory-storage' out of this class/code ?

    https://github.com/cenkalti/rain/tree/master/internal/storage

    Thanks !

  • Should add timeout for udp trackers in PeriodicalAnnouncer

    Should add timeout for udp trackers in PeriodicalAnnouncer

    When the Periodical Announcer call doAnnounce with context, the context has no timeout, so it will block when a udp tracker hangs in network.

    And when udp tracker Announce hangs, it has connection lock, so then call torrent.Stop, the torrent.NotifyStop will hangs too.

    So in a session, if any udp tracker hangs in network, the stop of any torrent task will hangs for a long time (if these torrents share the same udp tracker, such as extra trackers list) , this is very bad.

    Maybe, in internal/announcer/periodic.go, the ctx should be context.WithTimeout:

    // Run the announcer goroutine. Invoke with go statement.
    
    func (a *PeriodicalAnnouncer) Run() {
    ...
    	ctx, cancel := context.WithCancel(context.Background())
    ...
    
  • Speed limit issue

    Speed limit issue

    Hello.

    I found an issue with the global download speed limit working. I have same results for tests with and without a download speed limit.

    Input data

    • golang 1.17
    • github.com/cenkalti/rain v1.8.1
    • used the same torrent file for both tests
    • ./torrent.db and data folder clean

    Test code

    func main() {
    	var limit int64
    
    	flag.Int64Var(&limit, "limit", 0, "download limit")
    	flag.Parse()
    
    	fmt.Printf("Global speed limit is %d KBps\n", limit)
    
    	cfg := torrent.DefaultConfig
    	cfg.DataDir = "./data"
    	cfg.Database = "./torrent.db"
    	cfg.SpeedLimitDownload = limit
    
    	c, _ := torrent.NewSession(cfg)
    	defer c.Close()
    
    	f, _ := os.Open("test.torrent")
    	defer f.Close()
    
    	t, _ := c.AddTorrent(f, nil)
    
    	for {
    		select {
    		case <-t.NotifyComplete():
    			fmt.Println("Done!")
    			return
    		case <-time.Tick(10 * time.Second):
    			speedKbps := t.Stats().Speed.Download / 1024
    			fmt.Printf("Speed is %d KBps\n", speedKbps)
    		}
    	}
    }
    

    Test without download limit

    # time ./test_torrent
    Global speed limit is 0 KBps
    2021-11-02 12:54:52 INFO     [session] session_load.go:34 loaded 0 existing torrents
    2021-11-02 12:54:52 INFO     [rpc server] session_rpc_server.go:48 RPC server is listening on 127.0.0.1:7246
    2021-11-02 12:54:52 INFO     [torrent 7JTQVDvCEey413Tl-RSrzA] session_add.go:284 added torrent
    2021-11-02 12:54:52 INFO     [torrent 7JTQVDvCEey413Tl-RSrzA] torrent_start.go:31 starting torrent
    2021-11-02 12:54:52 INFO     [torrent 7JTQVDvCEey413Tl-RSrzA] torrent_start.go:118 Listening peers on tcp://0.0.0.0:50898
    Speed is 6315 KBps
    Speed is 6492 KBps
    Speed is 6613 KBps
    Speed is 6629 KBps
    Speed is 6756 KBps
    Done!
    2021-11-02 12:55:43 INFO     [torrent 7JTQVDvCEey413Tl-RSrzA] torrent_write.go:82 download completed
    2021-11-02 12:55:43 INFO     [torrent 7JTQVDvCEey413Tl-RSrzA] torrent_stop.go:46 stopping torrent
    
    real    0m51,059s
    user    0m8,361s
    sys     0m11,401s
    

    Test with download limit

    # time ./test_torrent --limit=1024
    Global speed limit is 1024 KBps
    2021-11-02 12:56:24 INFO     [session] session_load.go:34 loaded 0 existing torrents
    2021-11-02 12:56:24 INFO     [rpc server] session_rpc_server.go:48 RPC server is listening on 127.0.0.1:7246
    2021-11-02 12:56:24 INFO     [torrent I2naazvDEeyA0nTl-RSrzA] session_add.go:284 added torrent
    2021-11-02 12:56:24 INFO     [torrent I2naazvDEeyA0nTl-RSrzA] torrent_start.go:31 starting torrent
    2021-11-02 12:56:24 INFO     [torrent I2naazvDEeyA0nTl-RSrzA] torrent_start.go:118 Listening peers on tcp://0.0.0.0:55204
    Speed is 6883 KBps
    Speed is 7022 KBps
    Speed is 6936 KBps
    Speed is 6922 KBps
    Speed is 6930 KBps
    Done!
    2021-11-02 12:57:15 INFO     [torrent I2naazvDEeyA0nTl-RSrzA] torrent_write.go:82 download completed
    2021-11-02 12:57:15 INFO     [torrent I2naazvDEeyA0nTl-RSrzA] torrent_stop.go:46 stopping torrent
    
    real    0m51,494s
    user    0m8,410s
    sys     0m11,407s
    
  • Health check crashes while printing a log statement

    Health check crashes while printing a log statement

    I don't know what could be done to help with those problems. Here is what the goroutine stacks looks like (edited a bit).

    goroutine 130 [select]:
    github.com/nictuku/nettools.(*ClientThrottle).cleanup(0xc000578060)
    	/var/lib/jenkins/go/pkg/mod/github.com/nictuku/[email protected]/ratelimit.go:78 +0x92
    created by github.com/nictuku/nettools.NewThrottler
    	/var/lib/jenkins/go/pkg/mod/github.com/nictuku/[email protected]/ratelimit.go:19 +0x21e
    
    goroutine 132 [select]:
    github.com/nictuku/dht.(*DHT).loop(0xc00057a000)
    	/var/lib/jenkins/go/pkg/mod/github.com/nictuku/[email protected]/dht.go:435 +0x5d2
    github.com/nictuku/dht.(*DHT).Start.func1()
    	/var/lib/jenkins/go/pkg/mod/github.com/nictuku/[email protected]/dht.go:338 +0x5d
    created by github.com/nictuku/dht.(*DHT).Start
    	/var/lib/jenkins/go/pkg/mod/github.com/nictuku/[email protected]/dht.go:336 +0x8f
    
    goroutine 146 [IO wait]:
    internal/poll.runtime_pollWait(0x7f8cd4938798, 0x72)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/runtime/netpoll.go:229 +0x89
    internal/poll.(*pollDesc).wait(0xc0001bc080, 0xc000592000, 0x0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
    internal/poll.(*pollDesc).waitRead(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_poll_runtime.go:89
    internal/poll.(*FD).ReadFrom(0xc0001bc080, {0xc000592000, 0x1000, 0x1000})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:223 +0x238
    net.(*netFD).readFrom(0xc0001bc080, {0xc000592000, 0xffffffffffffffff, 0x0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_posix.go:62 +0x29
    net.(*UDPConn).readFrom(0xc0002918e8, {0xc000592000, 0x4cd320, 0xc000353e90}, 0xc000353eb0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/udpsock_posix.go:47 +0x3e
    net.(*UDPConn).readFromUDP(0xc000388058, {0xc000592000, 0x0, 0x1}, 0x0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/udpsock.go:116 +0x31
    net.(*UDPConn).ReadFromUDP(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/udpsock.go:108
    github.com/nictuku/dht.readFromSocket(0x0, 0xc0003ea060, 0x0, 0xc000158120, {0xe2c370, 0x15323e8})
    	/var/lib/jenkins/go/pkg/mod/github.com/nictuku/[email protected]/krpc.go:235 +0xc7
    github.com/nictuku/dht.(*DHT).loop.func1()
    	/var/lib/jenkins/go/pkg/mod/github.com/nictuku/[email protected]/dht.go:406 +0x85
    created by github.com/nictuku/dht.(*DHT).loop
    	/var/lib/jenkins/go/pkg/mod/github.com/nictuku/[email protected]/dht.go:404 +0x1c7
    
    goroutine 4558 [select]:
    github.com/cenkalti/rain/internal/peerconn.(*Conn).Run(0xc00058f8b0)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:107 +0x45e
    created by github.com/cenkalti/rain/internal/peer.(*Peer).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peer/peer.go:153 +0xef
    
    goroutine 133 [chan receive]:
    github.com/rcrowley/go-metrics.(*meterArbiter).tick(0x14f8b40)
    	/var/lib/jenkins/go/pkg/mod/github.com/rcrowley/[email protected]/meter.go:239 +0x2a
    created by github.com/rcrowley/go-metrics.NewMeter
    	/var/lib/jenkins/go/pkg/mod/github.com/rcrowley/[email protected]/meter.go:46 +0xd8
    
    goroutine 134 [select]:
    github.com/cenkalti/rain/internal/resourcemanager.(*ResourceManager).run(0xc0001aa140)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/resourcemanager/resourcemanager.go:107 +0x265
    created by github.com/cenkalti/rain/internal/resourcemanager.New
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/resourcemanager/resourcemanager.go:46 +0x187
    
    goroutine 105 [select]:
    github.com/cenkalti/rain/torrent.(*Session).processDHTResults(0xc000181c00)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_dht.go:12 +0x12e
    created by github.com/cenkalti/rain/torrent.NewSession
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session.go:228 +0x1272
    
    goroutine 106 [runnable]:
    syscall.Syscall(0x4b, 0x7, 0x0, 0x0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/syscall/asm_linux_amd64.s:20 +0x5
    syscall.Fdatasync(0xc747e0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/syscall/zsyscall_linux_amd64.go:394 +0x30
    go.etcd.io/bbolt.fdatasync(0xc004565000)
    	/var/lib/jenkins/go/pkg/mod/go.etcd.io/[email protected]/bolt_linux.go:9 +0x4d
    go.etcd.io/bbolt.(*Tx).write(0xc00027e000)
    	/var/lib/jenkins/go/pkg/mod/go.etcd.io/[email protected]/tx.go:558 +0x24c
    go.etcd.io/bbolt.(*Tx).Commit(0xc00027e000)
    	/var/lib/jenkins/go/pkg/mod/go.etcd.io/[email protected]/tx.go:185 +0x1dd
    go.etcd.io/bbolt.(*DB).Update(0x1, 0xc000015ea0)
    	/var/lib/jenkins/go/pkg/mod/go.etcd.io/[email protected]/db.go:748 +0xe5
    github.com/cenkalti/rain/torrent.(*Session).updateStats(0xc000181c00)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_stats.go:119 +0xcb
    github.com/cenkalti/rain/torrent.(*Session).updateStatsLoop(0xc000181c00)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_stats.go:109 +0x85
    created by github.com/cenkalti/rain/torrent.NewSession
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session.go:230 +0x12ba
    
    goroutine 110 [IO wait]:
    internal/poll.runtime_pollWait(0x7f8cd49385c8, 0x72)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/runtime/netpoll.go:229 +0x89
    internal/poll.(*pollDesc).wait(0xc0001bc100, 0x49b786, 0x0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
    internal/poll.(*pollDesc).waitRead(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_poll_runtime.go:89
    internal/poll.(*FD).Accept(0xc0001bc100)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:402 +0x22c
    net.(*netFD).accept(0xc0001bc100)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_unix.go:173 +0x35
    net.(*TCPListener).accept(0xc00045e030)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/tcpsock_posix.go:140 +0x28
    net.(*TCPListener).Accept(0xc00045e030)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/tcpsock.go:262 +0x3d
    net/http.(*Server).Serve(0xc00027e1c0, {0xe2c790, 0xc00045e030})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/server.go:3001 +0x394
    company.com/module.foo(0x0, 0xd590cc)
    	/var/lib/jenkins/workspace/ProjectName/foo.go:564 +0x28a
    
    goroutine 112 [select]:
    net/http.(*Transport).getConn(0x149d7e0, 0xc002cb40c0, {{}, 0x0, {0xc00834a000, 0x4}, {0xc0001ce020, 0x1b}, 0x0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1372 +0x5d2
    net/http.(*Transport).roundTrip(0x149d7e0, 0xc0001be500)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:581 +0x774
    net/http.(*Transport).RoundTrip(0xc0001be500, 0xe21d40)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/roundtrip.go:18 +0x19
    net/http.send(0xc0001be300, {0xe21d40, 0x149d7e0}, {0xd2c380, 0x542501, 0x14f9140})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:252 +0x5d8
    net/http.(*Client).send(0xc000300180, 0xc0001be300, {0xc0001be300, 0x24, 0x14f9140})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:176 +0x9b
    net/http.(*Client).do(0xc000300180, 0xc0001be300)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:725 +0x908
    net/http.(*Client).Do(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:593
    net/http.(*Client).Get(0xc000496150, {0xc00834a000, 0xd5284b})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:480 +0x6a
    ...
    
    goroutine 113 [select]:
    net/http.(*Transport).getConn(0x149d7e0, 0xc00020bf00, {{}, 0x0, {0xc0079ca050, 0x4}, {0xc0009600a0, 0x1b}, 0x0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1372 +0x5d2
    net/http.(*Transport).roundTrip(0x149d7e0, 0xc003c38300)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:581 +0x774
    net/http.(*Transport).RoundTrip(0xc003c38300, 0xe21d40)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/roundtrip.go:18 +0x19
    net/http.send(0xc003c38200, {0xe21d40, 0x149d7e0}, {0xd2c380, 0x542501, 0x14f9140})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:252 +0x5d8
    net/http.(*Client).send(0xc00019c150, 0xc003c38200, {0xc003c38200, 0x2f, 0x14f9140})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:176 +0x9b
    net/http.(*Client).do(0xc00019c150, 0xc003c38200)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:725 +0x908
    net/http.(*Client).Do(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:593
    net/http.(*Client).Get(0xc0001d0070, {0xc0079ca050, 0xd5284b})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:480 +0x6a
    ...
    
    goroutine 162 [select]:
    net/http.(*Transport).getConn(0x149d7e0, 0xc00020bdc0, {{}, 0x0, {0xc00776e000, 0x4}, {0xc000960060, 0x1b}, 0x0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1372 +0x5d2
    net/http.(*Transport).roundTrip(0x149d7e0, 0xc003c38100)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:581 +0x774
    net/http.(*Transport).RoundTrip(0xc003c38100, 0xe21d40)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/roundtrip.go:18 +0x19
    net/http.send(0xc003c38000, {0xe21d40, 0x149d7e0}, {0xd2c380, 0x542501, 0x14f9140})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:252 +0x5d8
    net/http.(*Client).send(0xc0003003f0, 0xc003c38000, {0xc003c38000, 0x24, 0x14f9140})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:176 +0x9b
    net/http.(*Client).do(0xc0003003f0, 0xc003c38000)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:725 +0x908
    net/http.(*Client).Do(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:593
    net/http.(*Client).Get(0xc000496310, {0xc00776e000, 0xd5284b})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/client.go:480 +0x6a
    ...
    
    goroutine 163 [select]:
    github.com/cenkalti/rain/torrent.(*torrent).Stats(_)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_commands.go:136 +0xf5
    github.com/cenkalti/rain/torrent.(*Torrent).Stats(...)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_torrent.go:60
    company.com/module.RunDownloadTorrent(0xd53a4f, 0x1a, {0xc003f329c0, 0x5a}, 0x5)
    	...
    
    goroutine 121 [select]:
    github.com/cenkalti/rain/torrent.(*torrent).run(0xc00042db00)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_run.go:20 +0x7ca
    created by github.com/cenkalti/rain/torrent.newTorrent2
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent.go:375 +0x181a
    
    goroutine 154 [IO wait, 3 minutes]:
    internal/poll.runtime_pollWait(0x7f8cd49383f8, 0x72)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/runtime/netpoll.go:229 +0x89
    internal/poll.(*pollDesc).wait(0xc00018e180, 0xc0003a1800, 0x0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
    internal/poll.(*pollDesc).waitRead(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_poll_runtime.go:89
    internal/poll.(*FD).Read(0xc00018e180, {0xc0003a1800, 0x1784, 0x1784})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:167 +0x25a
    net.(*netFD).Read(0xc00018e180, {0xc0003a1800, 0xc000014f08, 0x0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_posix.go:56 +0x29
    net.(*conn).Read(0xc0001a2008, {0xc0003a1800, 0x2974b089, 0x15323e8})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/net.go:183 +0x45
    github.com/cenkalti/rain/internal/tracker/udptracker.(*Transport).readLoop(0xc0001aa0a0)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/tracker/udptracker/transport.go:143 +0x78
    created by github.com/cenkalti/rain/internal/tracker/udptracker.(*Transport).listen
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/tracker/udptracker/transport.go:87 +0x125
    
    goroutine 122 [select]:
    github.com/cenkalti/rain/torrent.(*Session).checkTorrent(0xc000181c00, 0xc00042db00)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_healthcheck.go:16 +0xc5
    created by github.com/cenkalti/rain/torrent.(*Session).addTorrentStopped
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_add.go:97 +0x48f
    
    goroutine 5812 [IO wait]:
    internal/poll.runtime_pollWait(0x7f8cc463e648, 0x77)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/runtime/netpoll.go:229 +0x89
    internal/poll.(*pollDesc).wait(0xc00031aa80, 0xc0005ea5a0, 0x0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
    internal/poll.(*pollDesc).waitWrite(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_poll_runtime.go:93
    internal/poll.(*FD).WaitWrite(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:529
    net.(*netFD).connect(0xc00031aa80, {0xe31c28, 0xc000387500}, {0xc0001eb428, 0x491694}, {0xe221e0, 0xc0001ce6e0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_unix.go:142 +0x717
    net.(*netFD).dial(0xc00031aa80, {0xe31c28, 0xc000387500}, {0xe37928, 0x0}, {0xe37928, 0xc0005ea510}, 0xc0001eb618)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/sock_posix.go:150 +0x379
    net.socket({0xe31c28, 0xc000387500}, {0xd41868, 0x3}, 0x2, 0x1, 0x0, 0x18, {0xe37928, 0x0}, ...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/sock_posix.go:71 +0x2a5
    net.internetSocket({0xe31c28, 0xc000387500}, {0xd41868, 0x3}, {0xe37928, 0x0}, {0xe37928, 0xc0005ea510}, 0xc001f9e080, 0x0, ...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/ipsock_posix.go:142 +0xf8
    net.(*sysDialer).doDialTCP(0xc00031aa00, {0xe31c28, 0xc000387500}, 0x0, 0xc8f4e0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/tcpsock_posix.go:66 +0xa5
    net.(*sysDialer).dialTCP(0xc000387500, {0xe31c28, 0xc000387500}, 0x294283c70d8fb009, 0x100)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/tcpsock_posix.go:62 +0x59
    net.(*sysDialer).dialSingle(0xc00031aa00, {0xe31c28, 0xc000387500}, {0xe2b318, 0xc0005ea510})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/dial.go:583 +0x28b
    net.(*sysDialer).dialSerial(0xc00031aa00, {0xe31c28, 0xc000387500}, {0xc0040ea1f0, 0x1, 0xd41cb6})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/dial.go:551 +0x312
    net.(*Dialer).DialContext(0xc000170240, {0xe31c28, 0xc000387500}, {0xd41868, 0x7f8cd40b8cf8}, {0xc000960060, 0x118})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/dial.go:428 +0x736
    net/http.(*Transport).dial(0xc000387500, {0xe31c28, 0xc000387500}, {0xd41868, 0x0}, {0xc000960060, 0x14b6260})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1166 +0xda
    net/http.(*Transport).dialConn(0x149d7e0, {0xe31c28, 0xc000387500}, {{}, 0x0, {0xc00776e000, 0x4}, {0xc000960060, 0x1b}, 0x0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1604 +0x845
    net/http.(*Transport).dialConnFor(0x8aec26, 0xc0001e42c0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1446 +0xb0
    created by net/http.(*Transport).queueForDial
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1415 +0x3d7
    
    goroutine 5716 [select]:
    github.com/cenkalti/rain/internal/peerconn/peerreader.(*PeerReader).Run(0xc003c7cd20)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerreader/peerreader.go:253 +0xe05
    created by github.com/cenkalti/rain/internal/peerconn.(*Conn).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:97 +0x1af
    
    goroutine 5704 [select]:
    github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).messageWriter(0xc0004f6b00)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:197 +0x34f
    created by github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:102 +0xb7
    
    goroutine 6133 [semacquire]:
    sync.runtime_Semacquire(0x591dee76eba21882)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/runtime/sema.go:56 +0x25
    sync.(*WaitGroup).Wait(0x15cbee640b855bf6)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/sync/waitgroup.go:130 +0x71
    github.com/prometheus/client_golang/prometheus.(*Registry).Gather.func2()
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/registry.go:463 +0x2f
    created by github.com/prometheus/client_golang/prometheus.(*Registry).Gather
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/registry.go:462 +0x56f
    
    goroutine 184 [select]:
    github.com/cenkalti/rain/torrent.(*torrent).run(0xc0004fc000)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_run.go:20 +0x7ca
    created by github.com/cenkalti/rain/torrent.newTorrent2
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent.go:375 +0x181a
    
    goroutine 143 [select]:
    github.com/cenkalti/rain/torrent.(*torrent).run(0xc0002ba480)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_run.go:20 +0x7ca
    created by github.com/cenkalti/rain/torrent.newTorrent2
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent.go:375 +0x181a
    
    goroutine 144 [select]:
    github.com/cenkalti/rain/torrent.(*Session).checkTorrent(0xc000181c00, 0xc0002ba480)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_healthcheck.go:16 +0xc5
    created by github.com/cenkalti/rain/torrent.(*Session).addTorrentStopped
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_add.go:97 +0x48f
    
    goroutine 185 [select]:
    github.com/cenkalti/rain/torrent.(*Session).checkTorrent(0xc000181c00, 0xc0004fc000)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_healthcheck.go:16 +0xc5
    created by github.com/cenkalti/rain/torrent.(*Session).addTorrentStopped
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_add.go:97 +0x48f
    
    goroutine 5642 [select]:
    github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).Run(0xc005c70000)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/announcer/periodic.go:158 +0x2dc
    created by github.com/cenkalti/rain/torrent.(*torrent).startNewAnnouncer
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_start.go:107 +0x48f
    
    goroutine 5655 [select, 3 minutes]:
    github.com/cenkalti/rain/internal/acceptor.(*Acceptor).Run.func1()
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/acceptor/acceptor.go:43 +0x65
    created by github.com/cenkalti/rain/internal/acceptor.(*Acceptor).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/acceptor/acceptor.go:42 +0x110
    
    goroutine 6123 [select]:
    net.(*netFD).connect.func2()
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_unix.go:119 +0x9e
    created by net.(*netFD).connect
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_unix.go:118 +0x385
    
    goroutine 2408 [select]:
    github.com/cenkalti/rain/torrent.(*Session).checkTorrent(0xc000181c00, 0xc000666900)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_healthcheck.go:16 +0xc5
    created by github.com/cenkalti/rain/torrent.(*Session).addTorrentStopped
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_add.go:97 +0x48f
    
    goroutine 5980 [select]:
    github.com/cenkalti/rain/internal/peer.(*Peer).Run(0xc000522a00, 0xc003f33980, 0xc003f339e0, 0xc003f33a40, 0xc003f33920)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peer/peer.go:167 +0x467
    created by github.com/cenkalti/rain/torrent.(*torrent).startPeer
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_peer.go:149 +0x4af
    
    goroutine 5701 [select]:
    github.com/cenkalti/rain/internal/peerconn.(*Conn).Run(0xc007d33090)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:107 +0x45e
    created by github.com/cenkalti/rain/internal/peer.(*Peer).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peer/peer.go:153 +0xef
    
    goroutine 2260 [select]:
    github.com/cenkalti/rain/torrent.(*Session).checkTorrent(0xc000181c00, 0xc000666000)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_healthcheck.go:16 +0xc5
    created by github.com/cenkalti/rain/torrent.(*Session).addTorrentStopped
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_add.go:97 +0x48f
    
    goroutine 5703 [select, 1 minutes]:
    github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).Run(0xc0004f6b00)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:115 +0x1f9
    created by github.com/cenkalti/rain/internal/peerconn.(*Conn).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:100 +0x23b
    
    goroutine 5969 [runnable]:
    net._C2func_getaddrinfo(0xc0005560a0, 0x0, 0xc003caa0f0, 0xc0005a0040)
    	_cgo_gotypes.go:91 +0x56
    net.cgoLookupIPCNAME.func1({0xc0005560a0, 0xc0002f7d10, 0x79e2ed}, 0xc003e48d56, 0xc000781440)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/cgo_unix.go:163 +0x9f
    net.cgoLookupIPCNAME({0xd41477, 0x2}, {0xc003e48d56, 0xc000758768})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/cgo_unix.go:163 +0x16d
    net.cgoIPLookup(0x57d6f0, {0xd41477, 0xe3d601}, {0xc003e48d56, 0x15320a0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/cgo_unix.go:220 +0x3b
    created by net.cgoLookupIP
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/cgo_unix.go:230 +0x125
    
    goroutine 5750 [select]:
    github.com/cenkalti/rain/internal/peer.(*Peer).Run(0xc002531500, 0xc003f33980, 0xc003f339e0, 0xc003f33a40, 0xc003f33920)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peer/peer.go:176 +0x32f
    created by github.com/cenkalti/rain/torrent.(*torrent).startPeer
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_peer.go:149 +0x4af
    
    goroutine 5715 [select]:
    github.com/cenkalti/rain/internal/peerconn.(*Conn).Run(0xc00058f950)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:107 +0x45e
    created by github.com/cenkalti/rain/internal/peer.(*Peer).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peer/peer.go:153 +0xef
    
    goroutine 5652 [runnable]:
    runtime.CallersFrames(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/runtime/symtab.go:66
    runtime.Caller(0x2)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/runtime/extern.go:203 +0x7e
    github.com/cenkalti/log.(*logger).log(0xc0003017a0, 0x5, {0xc0004fa030, 0x2d})
    	/var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/logger.go:89 +0x4e
    github.com/cenkalti/log.(*logger).Debugf(0xc0002ec000, {0xd5a63d, 0xc002531300}, {0xc007940000, 0xc005196000, 0x400000})
    	/var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/logger.go:209 +0x4c
    github.com/cenkalti/rain/torrent.(*torrent).startSinglePieceDownloader(0xc003f0c900, 0xc002531300)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_start.go:228 +0x31f
    github.com/cenkalti/rain/torrent.(*torrent).startPieceDownloaderFor(0xc003f0c900, 0xc002531300)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_start.go:206 +0xe7
    github.com/cenkalti/rain/torrent.(*torrent).handlePieceMessage(0xc003f0c900, {0xc002531300, {{0x299, 0x3fc000}, {{0xc001c2a000, 0x4000, 0x4000}, 0xc007d7e270, 0xc00019c570}}})
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_messagehandler.go:104 +0x9e5
    github.com/cenkalti/rain/torrent.(*torrent).run(0xc003f0c900)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_run.go:86 +0xf85
    created by github.com/cenkalti/rain/torrent.newTorrent2
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent.go:375 +0x181a
    
    goroutine 4557 [select]:
    github.com/cenkalti/rain/internal/peer.(*Peer).Run(0xc002531300, 0xc003f33980, 0xc003f339e0, 0xc003f33a40, 0xc003f33920)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peer/peer.go:176 +0x32f
    created by github.com/cenkalti/rain/torrent.(*torrent).startPeer
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_peer.go:149 +0x4af
    
    goroutine 2426 [select]:
    github.com/cenkalti/rain/torrent.(*torrent).run(0xc0004fcd80)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_run.go:20 +0x7ca
    created by github.com/cenkalti/rain/torrent.newTorrent2
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent.go:375 +0x181a
    
    goroutine 2259 [select]:
    github.com/cenkalti/rain/torrent.(*torrent).run(0xc000666000)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_run.go:20 +0x7ca
    created by github.com/cenkalti/rain/torrent.newTorrent2
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent.go:375 +0x181a
    
    goroutine 5700 [select]:
    github.com/cenkalti/rain/internal/peer.(*Peer).Run(0xc002a25300, 0xc003f33980, 0xc003f339e0, 0xc003f33a40, 0xc003f33920)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peer/peer.go:167 +0x467
    created by github.com/cenkalti/rain/torrent.(*torrent).startPeer
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_peer.go:149 +0x4af
    
    goroutine 4586 [select]:
    github.com/nictuku/dht.pingSlowly(0xc00075b7d0, {0xc00074a000, 0x306, 0xc003f33aa0}, 0xc003d52600, 0xc000158120)
    	/var/lib/jenkins/go/pkg/mod/github.com/nictuku/[email protected]/routing_table.go:292 +0x114
    github.com/nictuku/dht.(*DHT).loop.func2()
    	/var/lib/jenkins/go/pkg/mod/github.com/nictuku/[email protected]/dht.go:510 +0x85
    created by github.com/nictuku/dht.(*DHT).loop
    	/var/lib/jenkins/go/pkg/mod/github.com/nictuku/[email protected]/dht.go:508 +0xb05
    
    goroutine 5753 [select, 1 minutes]:
    github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).Run(0xc0001bd200)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:115 +0x1f9
    created by github.com/cenkalti/rain/internal/peerconn.(*Conn).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:100 +0x23b
    
    goroutine 1195 [select]:
    github.com/cenkalti/rain/torrent.(*Session).checkTorrent(0xc000181c00, 0xc000666480)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_healthcheck.go:16 +0xc5
    created by github.com/cenkalti/rain/torrent.(*Session).addTorrentStopped
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_add.go:97 +0x48f
    
    goroutine 5643 [runnable]:
    syscall.Syscall(0x3, 0x10, 0x0, 0x0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/syscall/asm_linux_amd64.s:20 +0x5
    syscall.Close(0x7f8cd4938228)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/syscall/zsyscall_linux_amd64.go:286 +0x30
    internal/poll.(*FD).destroy(0xc0004f6880)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:84 +0x51
    internal/poll.(*FD).readUnlock(0xc0004f6880)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_mutex.go:232 +0x33
    internal/poll.(*FD).Read(0xc0004f6880, {0xc0119f4000, 0x400000, 0x400000})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:173 +0x31e
    net.(*netFD).Read(0xc0004f6880, {0xc0119f4000, 0x82572d, 0x824b85})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_posix.go:56 +0x29
    net.(*conn).Read(0xc00063a1a0, {0xc0119f4000, 0x0, 0x0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/net.go:183 +0x45
    net/http.(*persistConn).Read(0xc005c70120, {0xc0119f4000, 0x0, 0x0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1926 +0x4e
    bufio.(*Reader).Read(0xc0005dbf20, {0xc0119f4000, 0x400000, 0x400000})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/bufio/bufio.go:213 +0x106
    io.(*LimitedReader).Read(0xc007d7e0a8, {0xc0119f4000, 0x491705, 0x1000000004e5e7a})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/io/io.go:473 +0x45
    net/http.(*body).readLocked(0xc0013c68c0, {0xc0119f4000, 0x400000, 0xc000306000})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transfer.go:843 +0x3c
    net/http.(*body).Read(0x8, {0xc0119f4000, 0x400000, 0xc0079da4f8})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transfer.go:835 +0x125
    net/http.(*bodyEOFSignal).Read(0xc0013c6900, {0xc0119f4000, 0x400000, 0x400000})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:2768 +0x142
    github.com/cenkalti/rain/internal/urldownloader.readFull({0xe21d60, 0xc0013c6900}, {0xc0119f4000, 0x400000, 0x400000}, 0x52, 0x0)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/urldownloader/urldownloader.go:159 +0x79
    github.com/cenkalti/rain/internal/urldownloader.(*URLDownloader).Run.func2({{0xc003e48990, 0x400000}, 0x4ea64e, 0x29b00000000})
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/urldownloader/urldownloader.go:115 +0x945
    github.com/cenkalti/rain/internal/urldownloader.(*URLDownloader).Run(0xc0007f8450, 0xc000181ed0, {0xc001476000, 0x29b, 0x29b}, 0x0, 0xc003d52540, 0xc000301a70, 0x2540be400)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/urldownloader/urldownloader.go:138 +0x385
    created by github.com/cenkalti/rain/torrent.(*torrent).startWebseedDownloader
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_start.go:193 +0x45f
    
    goroutine 5968 [select]:
    net.cgoLookupIP({0xe31bb8, 0xc00838e040}, {0xd41477, 0x18}, {0xc003e48d56, 0xc000593000})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/cgo_unix.go:231 +0x1b7
    net.(*Resolver).lookupIP(0x14f7e40, {0xe31bb8, 0xc00838e040}, {0xd41477, 0x2}, {0xc003e48d56, 0x18})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/lookup_unix.go:97 +0x128
    net.glob..func1({0xe31bb8, 0xc00838e040}, 0x68, {0xd41477, 0x70}, {0xc003e48d56, 0x400000})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/hook.go:23 +0x3d
    net.(*Resolver).lookupIPAddr.func1()
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/lookup.go:296 +0x9f
    internal/singleflight.(*Group).doCall(0x14f7e50, 0xc008e84690, {0xc000556040, 0x1b}, 0xc000276810)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/singleflight/singleflight.go:95 +0x3b
    created by internal/singleflight.(*Group).DoChan
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/singleflight/singleflight.go:88 +0x2f1
    
    goroutine 5983 [select, 1 minutes]:
    github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).Run(0xc0001bc300)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:115 +0x1f9
    created by github.com/cenkalti/rain/internal/peerconn.(*Conn).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:100 +0x23b
    
    goroutine 5717 [select, 1 minutes]:
    github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).Run(0xc0001bd000)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:115 +0x1f9
    created by github.com/cenkalti/rain/internal/peerconn.(*Conn).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:100 +0x23b
    
    goroutine 5702 [select]:
    github.com/cenkalti/rain/internal/peerconn/peerreader.(*PeerReader).Run(0xc0003145a0)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerreader/peerreader.go:253 +0xe05
    created by github.com/cenkalti/rain/internal/peerconn.(*Conn).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:97 +0x1af
    
    goroutine 4560 [select, 1 minutes]:
    github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).Run(0xc0001bcf00)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:115 +0x1f9
    created by github.com/cenkalti/rain/internal/peerconn.(*Conn).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:100 +0x23b
    
    goroutine 5718 [select]:
    github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).messageWriter(0xc0001bd000)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:197 +0x34f
    created by github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:102 +0xb7
    
    goroutine 2794 [select]:
    github.com/cenkalti/rain/internal/peer.(*Peer).Run(0xc000522300, 0xc003f33980, 0xc003f339e0, 0xc003f33a40, 0xc003f33920)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peer/peer.go:176 +0x32f
    created by github.com/cenkalti/rain/torrent.(*torrent).startPeer
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_peer.go:149 +0x4af
    
    goroutine 5714 [select]:
    github.com/cenkalti/rain/internal/peer.(*Peer).Run(0xc002531400, 0xc003f33980, 0xc003f339e0, 0xc003f33a40, 0xc003f33920)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peer/peer.go:176 +0x32f
    created by github.com/cenkalti/rain/torrent.(*torrent).startPeer
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_peer.go:149 +0x4af
    
    goroutine 2796 [select]:
    github.com/cenkalti/rain/internal/peerconn/peerreader.(*PeerReader).Run(0xc00141b620)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerreader/peerreader.go:253 +0xe05
    created by github.com/cenkalti/rain/internal/peerconn.(*Conn).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:97 +0x1af
    
    goroutine 4784 [select]:
    github.com/cenkalti/rain/torrent.(*torrent).run(0xc005ad7680)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_run.go:20 +0x7ca
    created by github.com/cenkalti/rain/torrent.newTorrent2
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent.go:375 +0x181a
    
    goroutine 1194 [select]:
    github.com/cenkalti/rain/torrent.(*torrent).run(0xc000666480)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_run.go:20 +0x7ca
    created by github.com/cenkalti/rain/torrent.newTorrent2
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent.go:375 +0x181a
    
    goroutine 2427 [select]:
    github.com/cenkalti/rain/torrent.(*Session).checkTorrent(0xc000181c00, 0xc0004fcd80)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_healthcheck.go:16 +0xc5
    created by github.com/cenkalti/rain/torrent.(*Session).addTorrentStopped
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_add.go:97 +0x48f
    
    goroutine 4785 [select]:
    github.com/cenkalti/rain/torrent.(*Session).checkTorrent(0xc000181c00, 0xc005ad7680)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_healthcheck.go:16 +0xc5
    created by github.com/cenkalti/rain/torrent.(*Session).addTorrentStopped
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/session_add.go:97 +0x48f
    
    goroutine 2795 [select]:
    github.com/cenkalti/rain/internal/peerconn.(*Conn).Run(0xc007a9ed20)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:107 +0x45e
    created by github.com/cenkalti/rain/internal/peer.(*Peer).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peer/peer.go:153 +0xef
    
    goroutine 6132 [runnable]:
    syscall.Syscall(0x0, 0x1a, 0xc0001da400, 0x200)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/syscall/asm_linux_amd64.s:20 +0x5
    syscall.read(0xc003f6c0c0, {0xc0001da400, 0x320200000001, 0xc00073e820})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/syscall/zsyscall_linux_amd64.go:687 +0x4d
    syscall.Read(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/syscall/syscall_unix.go:189
    internal/poll.ignoringEINTRIO(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:582
    internal/poll.(*FD).Read(0xc003f6c0c0, {0xc0001da400, 0x200, 0x200})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:163 +0x285
    os.(*File).read(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/os/file_posix.go:32
    os.(*File).Read(0xc000388068, {0xc0001da400, 0xc60880, 0xc00046af01})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/os/file.go:119 +0x5e
    io.(*LimitedReader).Read(0xc003dd65d0, {0xc0001da400, 0x18, 0x7f8cfd5cfa68})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/io/io.go:473 +0x45
    io.ReadAll({0xe21a80, 0xc003dd65d0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/io/io.go:633 +0xfe
    io/ioutil.ReadAll(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/io/ioutil/ioutil.go:27
    github.com/prometheus/procfs/internal/util.ReadFileNoStat({0xc0005e60f0, 0xc000144070})
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/internal/util/readfile.go:37 +0xd4
    github.com/prometheus/procfs.FS.Stat({{_, _}})
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/stat.go:169 +0x126
    github.com/prometheus/procfs.ProcStat.StartTime({0x9704, {0xc0005e6050, 0xc}, {0x14c11d0, 0x1}, 0x1, 0x9704, 0x9704, 0x0, 0xffffffffffffffff, ...})
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/proc_stat.go:179 +0x78
    github.com/prometheus/client_golang/prometheus.(*processCollector).processCollect(0xc0001aa9b0, 0xc000352f20)
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/process_collector_other.go:44 +0x725
    github.com/prometheus/client_golang/prometheus.(*processCollector).Collect(0xc000352fb0, 0xc000352f60)
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/process_collector.go:138 +0x1f
    github.com/prometheus/client_golang/prometheus.(*Registry).Gather.func1()
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/registry.go:446 +0x102
    created by github.com/prometheus/client_golang/prometheus.(*Registry).Gather
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/registry.go:457 +0x4e8
    
    goroutine 2407 [select]:
    github.com/cenkalti/rain/torrent.(*torrent).run(0xc000666900)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_run.go:20 +0x7ca
    created by github.com/cenkalti/rain/torrent.newTorrent2
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent.go:375 +0x181a
    
    goroutine 6122 [select]:
    net.(*netFD).connect.func2()
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_unix.go:119 +0x9e
    created by net.(*netFD).connect
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_unix.go:118 +0x385
    
    goroutine 6124 [select]:
    net.(*netFD).connect.func2()
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_unix.go:119 +0x9e
    created by net.(*netFD).connect
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_unix.go:118 +0x385
    
    goroutine 5752 [select]:
    github.com/cenkalti/rain/internal/peerconn/peerreader.(*PeerReader).Run(0xc003c7da40)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerreader/peerreader.go:253 +0xe05
    created by github.com/cenkalti/rain/internal/peerconn.(*Conn).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:97 +0x1af
    
    goroutine 5813 [runnable]:
    internal/poll.runtime_pollWait(0x7f8cd4937a00, 0x77)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/runtime/netpoll.go:229 +0x89
    internal/poll.(*pollDesc).wait(0xc00031a800, 0xc0005ea420, 0x0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
    internal/poll.(*pollDesc).waitWrite(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_poll_runtime.go:93
    internal/poll.(*FD).WaitWrite(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:529
    net.(*netFD).connect(0xc00031a800, {0xe31c28, 0xc000387aa0}, {0xc0001ed428, 0x491694}, {0xe221e0, 0xc0001ce240})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_unix.go:142 +0x717
    net.(*netFD).dial(0xc00031a800, {0xe31c28, 0xc000387aa0}, {0xe37928, 0x0}, {0xe37928, 0xc0005ea3f0}, 0xc0001ed618)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/sock_posix.go:150 +0x379
    net.socket({0xe31c28, 0xc000387aa0}, {0xd41868, 0x3}, 0x2, 0x1, 0x0, 0x18, {0xe37928, 0x0}, ...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/sock_posix.go:71 +0x2a5
    net.internetSocket({0xe31c28, 0xc000387aa0}, {0xd41868, 0x3}, {0xe37928, 0x0}, {0xe37928, 0xc0005ea3f0}, 0xc001f9e080, 0x0, ...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/ipsock_posix.go:142 +0xf8
    net.(*sysDialer).doDialTCP(0xc00031a280, {0xe31c28, 0xc000387aa0}, 0x0, 0xc8f4e0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/tcpsock_posix.go:66 +0xa5
    net.(*sysDialer).dialTCP(0xc000387aa0, {0xe31c28, 0xc000387aa0}, 0x49b786, 0x2000)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/tcpsock_posix.go:62 +0x59
    net.(*sysDialer).dialSingle(0xc00031a280, {0xe31c28, 0xc000387aa0}, {0xe2b318, 0xc0005ea3f0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/dial.go:583 +0x28b
    net.(*sysDialer).dialSerial(0xc00031a280, {0xe31c28, 0xc000387aa0}, {0xc0040ea1b0, 0x1, 0xd41cb6})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/dial.go:551 +0x312
    net.(*Dialer).DialContext(0xc000170240, {0xe31c28, 0xc000387aa0}, {0xd41868, 0x7f8cd40b8cf8}, {0xc0009600a0, 0x118})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/dial.go:428 +0x736
    net/http.(*Transport).dial(0xc000387aa0, {0xe31c28, 0xc000387aa0}, {0xd41868, 0x0}, {0xc0009600a0, 0x14b6260})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1166 +0xda
    net/http.(*Transport).dialConn(0x149d7e0, {0xe31c28, 0xc000387aa0}, {{}, 0x0, {0xc0079ca050, 0x4}, {0xc0009600a0, 0x1b}, 0x0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1604 +0x845
    net/http.(*Transport).dialConnFor(0xe21620, 0xc0001e4370)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1446 +0xb0
    created by net/http.(*Transport).queueForDial
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1415 +0x3d7
    
    goroutine 5751 [select]:
    github.com/cenkalti/rain/internal/peerconn.(*Conn).Run(0xc0075efc20)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:107 +0x45e
    created by github.com/cenkalti/rain/internal/peer.(*Peer).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peer/peer.go:153 +0xef
    
    goroutine 2797 [select, 1 minutes]:
    github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).Run(0xc0002f4380)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:115 +0x1f9
    created by github.com/cenkalti/rain/internal/peerconn.(*Conn).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:100 +0x23b
    
    goroutine 5649 [semacquire]:
    internal/poll.runtime_Semacquire(0x7f8cd4938228)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/runtime/sema.go:61 +0x25
    internal/poll.(*FD).Close(0xc0004f6880)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:116 +0x6d
    net.(*netFD).Close(0xc0004f6880)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_posix.go:38 +0x38
    net.(*conn).Close(0xc00063a1a0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/net.go:207 +0x45
    net/http.(*persistConn).closeLocked(0xc005c70120, {0xe21620, 0xc0000209d0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:2708 +0x130
    net/http.(*persistConn).cancelRequest(0xc000709d40, {0xe21620, 0xc000020280})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1974 +0xe5
    net/http.(*Transport).cancelRequest(0xc00021a280, {0xc00055eda8}, {0xe21620, 0xc000020280})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:798 +0xee
    net/http.(*persistConn).readLoop(0xc005c70120)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:2223 +0xdf7
    created by net/http.(*Transport).dialConn
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1747 +0x1e05
    
    goroutine 5644 [select, 3 minutes]:
    github.com/cenkalti/rain/internal/urldownloader.(*URLDownloader).Run.func1()
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/urldownloader/urldownloader.go:78 +0x65
    created by github.com/cenkalti/rain/internal/urldownloader.(*URLDownloader).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/urldownloader/urldownloader.go:77 +0x13d
    
    goroutine 5641 [select]:
    github.com/cenkalti/rain/internal/acceptor.(*Acceptor).Run(0xc000f241c0)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/acceptor/acceptor.go:60 +0x1c7
    created by github.com/cenkalti/rain/torrent.(*torrent).startAcceptor
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/torrent/torrent_start.go:122 +0x3c8
    
    goroutine 5981 [select]:
    github.com/cenkalti/rain/internal/peerconn.(*Conn).Run(0xc0002f7d10)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:107 +0x45e
    created by github.com/cenkalti/rain/internal/peer.(*Peer).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peer/peer.go:153 +0xef
    
    goroutine 6134 [runnable]:
    syscall.Syscall(0x0, 0x19, 0xc002cb6000, 0x200)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/syscall/asm_linux_amd64.s:20 +0x5
    syscall.read(0xc00057c060, {0xc002cb6000, 0x490e01, 0x7f8cc46f1878})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/syscall/zsyscall_linux_amd64.go:687 +0x4d
    syscall.Read(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/syscall/syscall_unix.go:189
    internal/poll.ignoringEINTRIO(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:582
    internal/poll.(*FD).Read(0xc00057c060, {0xc002cb6000, 0x200, 0x200})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:163 +0x285
    os.(*File).read(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/os/file_posix.go:32
    os.(*File).Read(0xc00063a008, {0xc002cb6000, 0xc60880, 0xc000792f01})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/os/file.go:119 +0x5e
    io.(*LimitedReader).Read(0xc000602000, {0xc002cb6000, 0x18, 0x7f8cfd5d03c8})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/io/io.go:473 +0x45
    io.ReadAll({0xe21a80, 0xc000602000})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/io/io.go:633 +0xfe
    io/ioutil.ReadAll(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/io/ioutil/ioutil.go:27
    github.com/prometheus/procfs/internal/util.ReadFileNoStat({0xc003db4060, 0xc0001a4010})
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/internal/util/readfile.go:37 +0xd4
    github.com/prometheus/procfs.FS.Stat({{_, _}})
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/stat.go:169 +0x126
    github.com/prometheus/procfs.ProcStat.StartTime({0x9704, {0xc002140140, 0xc}, {0x14c11d8, 0x1}, 0x1, 0x9704, 0x9704, 0x0, 0xffffffffffffffff, ...})
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/proc_stat.go:179 +0x78
    github.com/prometheus/client_golang/prometheus.(*processCollector).processCollect(0xc0001567d0, 0xc000171e00)
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/process_collector_other.go:44 +0x725
    github.com/prometheus/client_golang/prometheus.(*processCollector).Collect(0xc00047afb0, 0xc00047af60)
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/process_collector.go:138 +0x1f
    github.com/prometheus/client_golang/prometheus.(*Registry).Gather.func1()
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/registry.go:446 +0x102
    created by github.com/prometheus/client_golang/prometheus.(*Registry).Gather
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/registry.go:538 +0xb4d
    
    goroutine 5666 [select, 3 minutes]:
    net/http.(*persistConn).writeLoop(0xc005c70120)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:2386 +0xfb
    created by net/http.(*Transport).dialConn
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1748 +0x1e65
    
    goroutine 6119 [runnable]:
    internal/poll.runtime_pollWait(0x7f8cd4938140, 0x77)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/runtime/netpoll.go:229 +0x89
    internal/poll.(*pollDesc).wait(0xc00031a980, 0xc0005ea4b0, 0x0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
    internal/poll.(*pollDesc).waitWrite(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_poll_runtime.go:93
    internal/poll.(*FD).WaitWrite(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/internal/poll/fd_unix.go:529
    net.(*netFD).connect(0xc00031a980, {0xe31c28, 0xc007aeaba0}, {0xc0007eb428, 0x491694}, {0xe221e0, 0xc0001ce6c0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/fd_unix.go:142 +0x717
    net.(*netFD).dial(0xc00031a980, {0xe31c28, 0xc007aeaba0}, {0xe37928, 0x0}, {0xe37928, 0xc0005ea480}, 0xc0007eb618)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/sock_posix.go:150 +0x379
    net.socket({0xe31c28, 0xc007aeaba0}, {0xd41868, 0x3}, 0x2, 0x1, 0x0, 0x18, {0xe37928, 0x0}, ...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/sock_posix.go:71 +0x2a5
    net.internetSocket({0xe31c28, 0xc007aeaba0}, {0xd41868, 0x3}, {0xe37928, 0x0}, {0xe37928, 0xc0005ea480}, 0xc001f9e080, 0x0, ...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/ipsock_posix.go:142 +0xf8
    net.(*sysDialer).doDialTCP(0xc00031a900, {0xe31c28, 0xc007aeaba0}, 0x0, 0xc8f4e0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/tcpsock_posix.go:66 +0xa5
    net.(*sysDialer).dialTCP(0xc007aeaba0, {0xe31c28, 0xc007aeaba0}, 0xefbc4b2c1df0c233, 0xccbfe824f0b815df)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/tcpsock_posix.go:62 +0x59
    net.(*sysDialer).dialSingle(0xc00031a900, {0xe31c28, 0xc007aeaba0}, {0xe2b318, 0xc0005ea480})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/dial.go:583 +0x28b
    net.(*sysDialer).dialSerial(0xc00031a900, {0xe31c28, 0xc007aeaba0}, {0xc0040ea1d0, 0x1, 0xd41cb6})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/dial.go:551 +0x312
    net.(*Dialer).DialContext(0xc000170240, {0xe31c28, 0xc007aeaba0}, {0xd41868, 0x7f8cd40b65a8}, {0xc0001ce020, 0x118})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/dial.go:428 +0x736
    net/http.(*Transport).dial(0xc007aeaba0, {0xe31c28, 0xc007aeaba0}, {0xd41868, 0x811cc3d00d01cfa7}, {0xc0001ce020, 0x3189c3ce469a236d})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1166 +0xda
    net/http.(*Transport).dialConn(0x149d7e0, {0xe31c28, 0xc007aeaba0}, {{}, 0x0, {0xc00834a000, 0x4}, {0xc0001ce020, 0x1b}, 0x0})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1604 +0x845
    net/http.(*Transport).dialConnFor(0xc003f33a40, 0xc003ef8000)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1446 +0xb0
    created by net/http.(*Transport).queueForDial
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/transport.go:1415 +0x3d7
    
    goroutine 4559 [select]:
    github.com/cenkalti/rain/internal/peerconn/peerreader.(*PeerReader).Run(0xc003c7cae0)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerreader/peerreader.go:253 +0xe05
    created by github.com/cenkalti/rain/internal/peerconn.(*Conn).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:97 +0x1af
    
    goroutine 5984 [select]:
    github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).messageWriter(0xc0001bc300)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:197 +0x34f
    created by github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:102 +0xb7
    
    goroutine 5982 [select]:
    github.com/cenkalti/rain/internal/peerconn/peerreader.(*PeerReader).Run(0xc007aea1e0)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerreader/peerreader.go:253 +0xe05
    created by github.com/cenkalti/rain/internal/peerconn.(*Conn).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerconn.go:97 +0x1af
    
    goroutine 5967 [select]:
    net.(*Resolver).lookupIPAddr(0x14f7e40, {0xe31c28, 0xc003c180c0}, {0xd41477, 0x49b00f}, {0xc003e48d56, 0x18})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/lookup.go:302 +0x5c7
    net.(*Resolver).LookupIPAddr(...)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/lookup.go:207
    github.com/cenkalti/rain/internal/resolver.ResolveIPv4({0xe31bb8, 0xc000518700}, 0x491694, {0xc003e48d56, 0x18})
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/resolver/resolver.go:57 +0xb2
    github.com/cenkalti/rain/internal/resolver.Resolve({0xe31bb8, 0xc000518700}, {0xc003e48d56, 0xc0020edc38}, 0x4919e7, 0xc000192300)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/resolver/resolver.go:37 +0xb2
    github.com/cenkalti/rain/internal/tracker/udptracker.(*Transport).Do(0xc0001aa0a0, {0xe31bb8, 0xc000518700}, 0xc003c18000)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/tracker/udptracker/transport.go:97 +0x7a
    github.com/cenkalti/rain/internal/tracker/udptracker.(*UDPTracker).Announce(0xc0003d6d20, {0xe31bb8, 0xc000518700}, {{0x2744000, 0x4f906d38, 0x58000000, {0xb1, 0xd2, 0x5b, 0x6d, ...}, ...}, ...})
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/tracker/udptracker/udptracker.go:67 +0x153
    github.com/cenkalti/rain/internal/tracker.(*Tier).Announce(0xc0077f4560, {0xe31bb8, 0xc000518700}, {{0x2744000, 0x4f906d38, 0x58000000, {0xb1, 0xd2, 0x5b, 0x6d, ...}, ...}, ...})
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/tracker/tier.go:32 +0x95
    github.com/cenkalti/rain/internal/announcer.announce({0xe31bb8, 0xc000518700}, {0xe2ac10, 0xc0077f4560}, 0x147a2c0, 0xc00abf2000, {0x2744000, 0x4f906d38, 0x58000000, {0xb1, ...}, ...}, ...)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/announcer/announce.go:24 +0x143
    github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).announce(0xc005c70000, {0xe31bb8, 0xc000518700}, 0x192600, 0xc000276810)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/announcer/periodic.go:244 +0x11e
    created by github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).doAnnounce
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/announcer/periodic.go:238 +0xb7
    
    goroutine 2798 [select]:
    github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).messageWriter(0xc0002f4380)
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:197 +0x34f
    created by github.com/cenkalti/rain/internal/peerconn/peerwriter.(*PeerWriter).Run
    	/var/lib/jenkins/go/pkg/mod/github.com/bsergean/[email protected]/internal/peerconn/peerwriter/peerwriter.go:102 +0xb7
    
    goroutine 5916 [select]:
    github.com/prometheus/client_golang/prometheus.(*Registry).Gather(0xc0001aa960)
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/registry.go:513 +0x945
    github.com/prometheus/client_golang/prometheus/promhttp.HandlerFor.func1({0x7f8cc419a278, 0xc003f73c70}, 0xc000392100)
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/promhttp/http.go:126 +0x108
    net/http.HandlerFunc.ServeHTTP(0xe22880, {0x7f8cc419a278, 0xc003f73c70}, 0xc0012de210)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/server.go:2046 +0x2f
    github.com/prometheus/client_golang/prometheus/promhttp.InstrumentHandlerInFlight.func1({0x7f8cc419a278, 0xc003f73c70}, 0xc003f73c70)
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/promhttp/instrument_server.go:40 +0xd4
    net/http.HandlerFunc.ServeHTTP(0xe2c9a0, {0x7f8cc419a278, 0xc003f73c70}, 0x716085)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/server.go:2046 +0x2f
    github.com/prometheus/client_golang/prometheus/promhttp.InstrumentHandlerCounter.func1({0xe2c9a0, 0xc0006780e0}, 0xc000392100)
    	/var/lib/jenkins/go/pkg/mod/github.com/prometheus/[email protected]/prometheus/promhttp/instrument_server.go:101 +0x92
    net/http.HandlerFunc.ServeHTTP(0x0, {0xe2c9a0, 0xc0006780e0}, 0x0)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/server.go:2046 +0x2f
    net/http.(*ServeMux).ServeHTTP(0x0, {0xe2c9a0, 0xc0006780e0}, 0xc000392100)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/server.go:2424 +0x149
    net/http.serverHandler.ServeHTTP({0xc00078bda0}, {0xe2c9a0, 0xc0006780e0}, 0xc000392100)
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/server.go:2878 +0x43b
    net/http.(*conn).serve(0xc0011cc140, {0xe31c60, 0xc00019c690})
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/server.go:1929 +0xb08
    created by net/http.(*Server).Serve
    	/var/lib/jenkins/workspace/ProjectName/golang/go/src/net/http/server.go:3033 +0x4e8
    
  • Status: Stopped: file allocation error

    Status: Stopped: file allocation error

    previously, i nothing issue using rain as torrent client, currently i have an issue when i download a file with size 104597 MiB , i'm not sure this issue about size

    here general info about my torrent

    Name: Mytorrent-test
    Private: false
    Status: Stopped: file allocation error: open /root/rain/data/CsifRcHWEeyOJwLUlt2y4A/Mytorrent-test/media/Stripped/MediaOverride/x10/test/CHARACTER_Driver.zip: too many open files
    Progress: 0%
    Ratio: 0.00
    Size: 104597 MiB
    Peers: 0 in / 0 out
    Download speed:     0 KiB/s
    Upload speed:       0 KiB/s
    ETA:
    
  • Patch #35

    Patch #35

    See https://github.com/cenkalti/rain/issues/35

    I am not super sure if we need both mutex, because it is probably the same torrents that are stuffed in the 2 maps.

  • Data race in Tier.go Announce method

    Data race in Tier.go Announce method

    I have 2 sessions objects, and I run a download for both.

    Here is the race report.

    ==================
    WARNING: DATA RACE
    Read at 0x00c000666678 by goroutine 81:
      github.com/cenkalti/rain/internal/tracker.(*Tier).Announce()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/internal/tracker/tier.go:27 +0xb9
      github.com/cenkalti/rain/internal/announcer.announce()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/internal/announcer/announce.go:24 +0x18f
      github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).announce()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/internal/announcer/periodic.go:244 +0x1fc
      github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).doAnnounce·dwrap·5()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/internal/announcer/periodic.go:238 +0x6e
    
    Previous write at 0x00c000666678 by goroutine 151:
      github.com/cenkalti/rain/internal/tracker.(*Tier).Announce()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/internal/tracker/tier.go:29 +0x1c4
      github.com/cenkalti/rain/internal/announcer.announce()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/internal/announcer/announce.go:24 +0x18f
      github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).announce()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/internal/announcer/periodic.go:244 +0x1fc
      github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).doAnnounce·dwrap·5()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/internal/announcer/periodic.go:238 +0x6e
    
    Goroutine 81 (running) created at:
      github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).doAnnounce()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/internal/announcer/periodic.go:238 +0x110
      github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).Run()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/internal/announcer/periodic.go:209 +0x10ec
      github.com/cenkalti/rain/torrent.(*torrent).startNewAnnouncer·dwrap·45()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/torrent/torrent_start.go:107 +0x39
    
    Goroutine 151 (finished) created at:
      github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).doAnnounce()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/internal/announcer/periodic.go:238 +0x110
      github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).Run()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/internal/announcer/periodic.go:156 +0x284
      github.com/cenkalti/rain/torrent.(*torrent).startNewAnnouncer·dwrap·45()
          /var/lib/jenkins/go/pkg/mod/github.com/cenkalti/[email protected]/torrent/torrent_start.go:107 +0x39
    ==================
    

    If I read this right, the problem is in this file

    // Announce a torrent to the tracker.
    // If annouce fails, the next announce will be made to the next Tracker in the tier.
    func (t *Tier) Announce(ctx context.Context, req AnnounceRequest) (*AnnounceResponse, error) {
        resp, err := t.Trackers[t.index].Announce(ctx, req) // line 27
        if err != nil {
            t.index = (t.index + 1) % len(t.Trackers) // line 29
        }
        return resp, err
    }
    

    on line 27 and 29 we are reading/writing t.index. Maybe a fix would be to make t.index an atomic int, and use atomic operations to get/set it ?

    Or maybe the problem is with the t.Trackers array ? I will try to something obvious (like adding a mutex to Tier) to debug this further.

  • Add completion command hook

    Add completion command hook

    This change adds an optional torrent completion command hook that executes a shell command defined in the server configuration (oncompletecmd). The executed command's shell environment is provided with specific variables relating to the completed torrent:

    • RAIN_TORRENT_ADDED: the torrent adding date (UNIX timestamp)
    • RAIN_TORRENT_DIR: the torrent download directory location
    • RAIN_TORRENT_HASH: the torrent info hash
    • RAIN_TORRENT_ID: the torrent internal ID in Rain
    • RAIN_TORRENT_NAME: the torrent name

    Implements #20.

  • Expose more details about torrent files

    Expose more details about torrent files

    Hi, I'm very interested in using this software, however I find it a bit terse regarding the files downloaded via the torrents. Could it be possible to expose more information via the RPC, such as file-level statistics (e.g. file list, size, % completion etc)? I'm thinking of trying to implement this in a fork and submit it to the original project for upstream integration if you're interested: if so, do you have tips as to where to start looking in the codebase?

    Thanks! 😊

Private BitTorrent tracker generator

Private BitTorrent tracker for everyone PrivTracker allows to share torrent files just with your fiends, nobody else. Unlike public trackers, it share

Jan 6, 2023
Golang client library for adding support for interacting and monitoring Celery workers, tasks and events.

Celeriac Golang client library for adding support for interacting and monitoring Celery workers and tasks. It provides functionality to place tasks on

Oct 28, 2022
dht is used by anacrolix/torrent, and is intended for use as a library in other projects both torrent related and otherwise

dht Installation Install the library package with go get github.com/anacrolix/dht, or the provided cmds with go get github.com/anacrolix/dht/cmd/....

Dec 28, 2022
Dec 27, 2022
A simple go implementation of json rpc 2.0 client over http

JSON-RPC 2.0 Client for golang A go implementation of an rpc client using json as data format over http. The implementation is based on the JSON-RPC 2

Dec 15, 2022
A feature complete and high performance multi-group Raft library in Go.
A feature complete and high performance multi-group Raft library in Go.

Dragonboat - A Multi-Group Raft library in Go / 中文版 News 2021-01-20 Dragonboat v3.3 has been released, please check CHANGELOG for all changes. 2020-03

Dec 30, 2022
Simple, fast and scalable golang rpc library for high load

gorpc Simple, fast and scalable golang RPC library for high load and microservices. Gorpc provides the following features useful for highly loaded pro

Dec 19, 2022
A Go library for master-less peer-to-peer autodiscovery and RPC between HTTP services

sleuth sleuth is a Go library that provides master-less peer-to-peer autodiscovery and RPC between HTTP services that reside on the same network. It w

Dec 28, 2022
A distributed systems library for Kubernetes deployments built on top of spindle and Cloud Spanner.

hedge A library built on top of spindle and Cloud Spanner that provides rudimentary distributed computing facilities to Kubernetes deployments. Featur

Nov 9, 2022
A distributed locking library built on top of Cloud Spanner and TrueTime.

A distributed locking library built on top of Cloud Spanner and TrueTime.

Sep 13, 2022
Easy to use Raft library to make your app distributed, highly available and fault-tolerant
Easy to use Raft library to make your app distributed, highly available and fault-tolerant

An easy to use customizable library to make your Go application Distributed, Highly available, Fault Tolerant etc... using Hashicorp's Raft library wh

Nov 16, 2022
Compute cluster (HPC) job submission library for Go (#golang) based on the open DRMAA standard.

go-drmaa This is a job submission library for Go (#golang) which is compatible to the DRMAA standard. The Go library is a wrapper around the DRMAA C l

Nov 17, 2022
Dynatomic is a library for using dynamodb as an atomic counter

Dynatomic Dynatomic is a library for using dynamodb as an atomic counter Dynatomic Motivation Usage Development Contributing Motivation The dynatomic

Sep 26, 2022
Library for enabling asynchronous health checks in your service

go-health A library that enables async dependency health checking for services running on an orchestrated container platform such as kubernetes or mes

Jan 4, 2023
A standard library for microservices.

Go kit Go kit is a programming toolkit for building microservices (or elegant monoliths) in Go. We solve common problems in distributed systems and ap

Jan 2, 2023
A library that implements the outboxer pattern in go

Outboxer Outboxer is a go library that implements the outbox pattern. Getting Started Outboxer was designed to simplify the tough work of orchestratin

Dec 16, 2022
An experimental library for building clustered services in Go

Donut is a library for building clustered applications in Go. Example package main import ( "context" "log" "os" // Wait for etcd client v3.4, t

Nov 17, 2022
Go Library [DEPRECATED]

Tideland Go Library Description The Tideland Go Library contains a larger set of useful Google Go packages for different purposes. ATTENTION: The cell

Nov 15, 2022
Lockgate is a cross-platform locking library for Go with distributed locks using Kubernetes or lockgate HTTP lock server as well as the OS file locks support.

Lockgate Lockgate is a locking library for Go. Classical interface: 2 types of locks: shared and exclusive; 2 modes of locking: blocking and non-block

Dec 16, 2022