Exemple #1
0
func main() {
	flag.Usage = usage
	flag.Parse()

	urls := flag.Args() // Non-flag arguments are URLs to receive from
	if len(urls) == 0 {
		log.Println("No URL provided")
		usage()
		os.Exit(1)
	}

	messages := make(chan amqp.Message) // Channel for messages from goroutines to main()
	defer close(messages)

	var wait sync.WaitGroup // Used by main() to wait for all goroutines to end.
	wait.Add(len(urls))     // Wait for one goroutine per URL.

	_, prog := path.Split(os.Args[0])
	container := electron.NewContainer(fmt.Sprintf("%v:%v", prog, os.Getpid()))
	connections := make(chan electron.Connection, len(urls)) // Connections to close on exit

	// Start a goroutine to for each URL to receive messages and send them to the messages channel.
	// main() receives and prints them.
	for _, urlStr := range urls {
		util.Debugf("Connecting to %s\n", urlStr)
		go func(urlStr string) { // Start the goroutine

			defer wait.Done()                 // Notify main() when this goroutine is done.
			url, err := amqp.ParseURL(urlStr) // Like net/url.Parse() but with AMQP defaults.
			util.ExitIf(err)

			// Open a new connection
			conn, err := net.Dial("tcp", url.Host) // Note net.URL.Host is actually "host:port"
			util.ExitIf(err)
			c, err := container.Connection(conn)
			connections <- c // Save connection so we can Close() when main() ends

			// Create a Receiver using the path of the URL as the source address
			r, err := c.Receiver(electron.Source(url.Path))
			util.ExitIf(err)

			// Loop receiving messages and sending them to the main() goroutine
			for {
				rm, err := r.Receive()
				switch err {
				case electron.Closed:
					util.Debugf("closed %s", urlStr)
					return
				case nil:
					messages <- rm.Message
				default:
					log.Fatal(err)
				}
			}
		}(urlStr)
	}

	// All goroutines are started, we are receiving messages.
	fmt.Printf("Listening on %d connections\n", len(urls))

	// print each message until the count is exceeded.
	for i := uint64(0); i < *count; i++ {
		m := <-messages
		util.Debugf("%s\n", util.FormatMessage(m))
	}
	fmt.Printf("Received %d messages\n", *count)

	// Close all connections, this will interrupt goroutines blocked in Receiver.Receive()
	for i := 0; i < len(urls); i++ {
		c := <-connections
		util.Debugf("close %s", c)
		c.Close(nil)
	}
	wait.Wait() // Wait for all goroutines to finish.
}
Exemple #2
0
func main() {
	flag.Usage = usage
	flag.Parse()

	urls := flag.Args() // Non-flag arguments are URLs to receive from
	if len(urls) == 0 {
		log.Println("No URL provided")
		flag.Usage()
		os.Exit(1)
	}

	sentChan := make(chan electron.Outcome) // Channel to receive acknowledgements.

	var wait sync.WaitGroup
	wait.Add(len(urls)) // Wait for one goroutine per URL.

	_, prog := path.Split(os.Args[0])
	container := electron.NewContainer(fmt.Sprintf("%v:%v", prog, os.Getpid()))
	connections := make(chan electron.Connection, len(urls)) // Connctions to close on exit

	// Start a goroutine for each URL to send messages.
	for _, urlStr := range urls {
		util.Debugf("Connecting to %v\n", urlStr)
		go func(urlStr string) {

			defer wait.Done()                 // Notify main() that this goroutine is done.
			url, err := amqp.ParseURL(urlStr) // Like net/url.Parse() but with AMQP defaults.
			util.ExitIf(err)

			// Open a new connection
			conn, err := net.Dial("tcp", url.Host) // Note net.URL.Host is actually "host:port"
			util.ExitIf(err)
			c, err := container.Connection(conn)
			util.ExitIf(err)
			connections <- c // Save connection so we can Close() when main() ends

			// Create a Sender using the path of the URL as the AMQP address
			s, err := c.Sender(electron.Target(url.Path))
			util.ExitIf(err)

			// Loop sending messages.
			for i := int64(0); i < *count; i++ {
				m := amqp.NewMessage()
				body := fmt.Sprintf("%v-%v", url.Path, i)
				m.Marshal(body)
				s.SendAsync(m, sentChan, body) // Outcome will be sent to sentChan
			}
		}(urlStr)
	}

	// Wait for all the acknowledgements
	expect := int(*count) * len(urls)
	util.Debugf("Started senders, expect %v acknowledgements\n", expect)
	for i := 0; i < expect; i++ {
		out := <-sentChan // Outcome of async sends.
		if out.Error != nil {
			util.Debugf("acknowledgement[%v] %v error: %v\n", i, out.Value, out.Error)
		} else {
			util.Debugf("acknowledgement[%v]  %v (%v)\n", i, out.Value, out.Status)
		}
	}
	fmt.Printf("Received all %v acknowledgements\n", expect)

	wait.Wait() // Wait for all goroutines to finish.
	close(connections)
	for c := range connections { // Close all connections
		if c != nil {
			c.Close(nil)
		}
	}
}