Example #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()
	stop := make(chan struct{})         // Closing this channel means the program is stopping.
	var wait sync.WaitGroup             // Used by main() to wait for all goroutines to end.
	wait.Add(len(urls))                 // Wait for one goroutine per URL.

	container := concurrent.NewContainer("")
	connections := make(chan concurrent.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.NewConnection(conn)
			util.ExitIf(err)
			util.ExitIf(c.Open())
			connections <- c // Save connection so we can Close() when main() ends

			// Create and open a session
			ss, err := c.NewSession()
			util.ExitIf(err)
			err = ss.Open()
			util.ExitIf(err)

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

			// Loop receiving messages and sending them to the main() goroutine
			for {
				rm, err := r.Receive()
				if err == concurrent.Closed {
					return
				}
				util.ExitIf(err)
				select { // Send m to main() or stop
				case messages <- rm.Message: // Send to main()
				case <-stop: // The program is stopping.
					return
				}
			}
		}(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
		c.Disconnect(nil) // FIXME aconway 2015-09-25: Close
	}
	close(stop) // Signal all goroutines to stop.
	wait.Wait() // Wait for all goroutines to finish.
	close(messages)
}
Example #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 sent) // Channel to receive all the delivery receipts.
	var wait sync.WaitGroup     // Used by main() to wait for all goroutines to end.
	wait.Add(len(urls))         // Wait for one goroutine per URL.

	container := concurrent.NewContainer("")
	var connections []concurrent.Connection // Store 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.NewConnection(conn)
			util.ExitIf(err)
			err = c.Open()
			util.ExitIf(err)
			connections = append(connections, c) // Save connection so it will be closed when main() ends

			// Create and open a session
			ss, err := c.NewSession()
			util.ExitIf(err)
			err = ss.Open()
			util.ExitIf(err)

			// Create a Sender using the path of the URL as the AMQP address
			s, err := ss.Sender(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)
				sentMessage, err := s.Send(m)
				util.ExitIf(err)
				sentChan <- sent{body, sentMessage}
			}
		}(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++ {
		d := <-sentChan
		disposition, err := d.sentMessage.Disposition()
		if err != nil {
			util.Debugf("acknowledgement[%v] %v error: %v\n", i, d.name, err)
		} else {
			util.Debugf("acknowledgement[%v]  %v (%v)\n", i, d.name, disposition)
		}
	}
	fmt.Printf("Received all %v acknowledgements\n", expect)

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