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  }