func main() { ///// ARGUMENT PARSING ////////////////////////////////////////////////////// flag.Parse() if *version { fmt.Printf("clique-agent v%s\n", clique.CliqueAgentVersion) os.Exit(0) } level := logrus.InfoLevel if *debug { level = logrus.DebugLevel } if *configPath == "" { fmt.Fprintf(os.Stderr, "`-config` option is required\n") os.Exit(1) } ///// LOGGING /////////////////////////////////////////////////////////////// logger := &logrus.Logger{ Out: os.Stdout, Level: level, Formatter: new(logrus.TextFormatter), } logger.Debug("Initializing internals...") ///// CONFIGURATION ///////////////////////////////////////////////////////// cfg, err := config.NewConfig(*configPath) if err != nil { logger.Fatal(err.Error()) } ///// TRANSFER ////////////////////////////////////////////////////////////// // Protocol t, err := setupTransferrer(logger, cfg) if err != nil { logger.Fatal(err.Error()) } // Server transferListener, err := net.Listen( "tcp", fmt.Sprintf("0.0.0.0:%d", cfg.TransferPort), ) if err != nil { logger.Fatalf("Setting up transfer server: %s", err.Error()) } transferServer := transfer.NewServer( logger, transferListener, t.transferReceiver, ) // Client transferConnector := transfer.NewConnector() transferClient := transfer.NewClient( logger, transferConnector, t.transferSender, ) ///// SCHEDULING //////////////////////////////////////////////////////////// schedRandGen := scheduler.NewCryptoUIG() schedTaskSelector := &scheduler.LotteryTaskSelector{ Rand: schedRandGen, } schedClock := clock.NewClock() sched := scheduler.NewScheduler( logger, schedTaskSelector, // scheduling algorithm time.Second, // sleep between tasks schedClock, ) ///// TRANSFER REGISTRY ///////////////////////////////////////////////////// transferRegistry := registry.NewRegistry() ///// DISPATCHER //////////////////////////////////////////////////////////// dsptchr := &dispatcher.Dispatcher{ Scheduler: sched, TransferInterruptible: t.interruptible, TransferClient: transferClient, ApiRegistry: transferRegistry, Logger: logger, } ///// API /////////////////////////////////////////////////////////////////// var apiServer *api.Server if cfg.APIPort != 0 { apiServer = api.NewServer( cfg.APIPort, transferRegistry, dsptchr, ) } ///// SIGNAL HANDLER //////////////////////////////////////////////////////// sigTermCh := make(chan os.Signal) signal.Notify(sigTermCh, os.Interrupt) signal.Notify(sigTermCh, syscall.SIGTERM) go func() { <-sigTermCh logger.Debug("Closing transfer server...") transferListener.Close() logger.Debug("Closing scheduler...") sched.Stop() if apiServer != nil { logger.Debug("Closing API server...") apiServer.Close() } logger.Info("Exitting clique-agent...") }() logger.Debug("Initialization is complete!") ///// START ///////////////////////////////////////////////////////////////// logger.Info("Clique Agent") // Populate the dispatcher with tasks if len(cfg.RemoteHosts) != 0 { createTransferTasks(logger, cfg, dsptchr) } wg := new(sync.WaitGroup) // Start the transfer server wg.Add(1) go func() { transferServer.Serve() logger.Debug("Transfer server is done.") wg.Done() }() // Start the scheduler wg.Add(1) go func() { sched.Run() logger.Debug("Scheduler is done.") wg.Done() }() // Start the API server if apiServer != nil { wg.Add(1) go func() { apiServer.Serve() logger.Debug("API server is done.") wg.Done() }() } // Wait until everything is done! wg.Wait() logger.Debug("Clique agent is done.") }
Describe("Client#Ping", func() { It("should return an error", func() { Expect(client.Ping()).NotTo(Succeed()) }) }) }) Context("when the server is started", func() { var serverChan chan struct{} BeforeEach(func() { serverChan = make(chan struct{}) go func() { defer GinkgoRecover() // it's going to fail... server.Serve() close(serverChan) }() Eventually(client.Ping).Should(Succeed()) }) Context("and closed immediately", func() { BeforeEach(func() { Expect(server.Close()).To(Succeed()) Eventually(serverChan).Should(BeClosed()) }) Describe("Server#Close", func() { It("should return an error", func() { Expect(server.Close()).NotTo(Succeed())