github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/exchange/bitswap/notifications/notifications.go (about) 1 package notifications 2 3 import ( 4 context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" 5 pubsub "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/tuxychandru/pubsub" 6 7 blocks "github.com/jbenet/go-ipfs/blocks" 8 u "github.com/jbenet/go-ipfs/util" 9 ) 10 11 type PubSub interface { 12 Publish(block blocks.Block) 13 Subscribe(ctx context.Context, k u.Key) <-chan blocks.Block 14 Shutdown() 15 } 16 17 func New() PubSub { 18 const bufferSize = 16 19 return &impl{*pubsub.New(bufferSize)} 20 } 21 22 type impl struct { 23 wrapped pubsub.PubSub 24 } 25 26 func (ps *impl) Publish(block blocks.Block) { 27 topic := string(block.Key()) 28 ps.wrapped.Pub(block, topic) 29 } 30 31 // Subscribe returns a one-time use |blockChannel|. |blockChannel| returns nil 32 // if the |ctx| times out or is cancelled. Then channel is closed after the 33 // block given by |k| is sent. 34 func (ps *impl) Subscribe(ctx context.Context, k u.Key) <-chan blocks.Block { 35 topic := string(k) 36 subChan := ps.wrapped.SubOnce(topic) 37 blockChannel := make(chan blocks.Block) 38 go func() { 39 defer close(blockChannel) 40 select { 41 case val := <-subChan: 42 block, ok := val.(blocks.Block) 43 if ok { 44 blockChannel <- block 45 } 46 case <-ctx.Done(): 47 ps.wrapped.Unsub(subChan, topic) 48 } 49 }() 50 return blockChannel 51 } 52 53 func (ps *impl) Shutdown() { 54 ps.wrapped.Shutdown() 55 }