Use retry when calling DMaaP and ECS
[nonrtric.git] / dmaap-mediator-producer / main.go
1 // -
2 //   ========================LICENSE_START=================================
3 //   O-RAN-SC
4 //   %%
5 //   Copyright (C) 2021: Nordix Foundation
6 //   %%
7 //   Licensed under the Apache License, Version 2.0 (the "License");
8 //   you may not use this file except in compliance with the License.
9 //   You may obtain a copy of the License at
10 //
11 //        http://www.apache.org/licenses/LICENSE-2.0
12 //
13 //   Unless required by applicable law or agreed to in writing, software
14 //   distributed under the License is distributed on an "AS IS" BASIS,
15 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 //   See the License for the specific language governing permissions and
17 //   limitations under the License.
18 //   ========================LICENSE_END===================================
19 //
20
21 package main
22
23 import (
24         "fmt"
25         "net/http"
26         "sync"
27         "time"
28
29         "github.com/hashicorp/go-retryablehttp"
30         log "github.com/sirupsen/logrus"
31         "oransc.org/nonrtric/dmaapmediatorproducer/internal/config"
32         "oransc.org/nonrtric/dmaapmediatorproducer/internal/jobs"
33         "oransc.org/nonrtric/dmaapmediatorproducer/internal/restclient"
34         "oransc.org/nonrtric/dmaapmediatorproducer/internal/server"
35 )
36
37 const timeoutDistributionClient = time.Second * 5
38 const retryWaitMax = time.Minute
39 const retryMax = int(^uint(0) >> 1)
40
41 var configuration *config.Config
42 var retryClient restclient.HTTPClient
43 var jobHandler *jobs.JobHandlerImpl
44
45 func init() {
46         configuration = config.New()
47 }
48
49 func main() {
50         log.SetLevel(configuration.LogLevel)
51         log.Debug("Initializing DMaaP Mediator Producer")
52         if err := validateConfiguration(configuration); err != nil {
53                 log.Fatalf("Stopping producer due to error: %v", err)
54         }
55         callbackAddress := fmt.Sprintf("%v:%v", configuration.InfoProducerHost, configuration.InfoProducerPort)
56
57         distributionClient := &http.Client{
58                 Timeout: timeoutDistributionClient,
59         }
60
61         rawRetryClient := retryablehttp.NewClient()
62         rawRetryClient.RetryWaitMax = retryWaitMax
63         rawRetryClient.RetryMax = retryMax
64         retryClient = rawRetryClient.StandardClient()
65
66         jobHandler = jobs.NewJobHandlerImpl("configs/type_config.json", retryClient, distributionClient)
67         if err := registerTypesAndProducer(jobHandler, configuration.InfoCoordinatorAddress, callbackAddress); err != nil {
68                 log.Fatalf("Stopping producer due to: %v", err)
69         }
70
71         log.Debug("Starting DMaaP Mediator Producer")
72         wg := new(sync.WaitGroup)
73
74         // add two goroutines to `wg` WaitGroup, one for each running go routine
75         wg.Add(2)
76
77         log.Debugf("Starting callback server at port %v", configuration.InfoProducerPort)
78         go func() {
79                 r := server.NewRouter(jobHandler)
80                 log.Warn(http.ListenAndServe(fmt.Sprintf(":%v", configuration.InfoProducerPort), r))
81                 wg.Done()
82         }()
83
84         go func() {
85                 jobHandler.RunJobs(fmt.Sprintf("%v:%v", configuration.MRHost, configuration.MRPort))
86                 wg.Done()
87         }()
88
89         // wait until WaitGroup is done
90         wg.Wait()
91         log.Debug("Stopping DMaaP Mediator Producer")
92 }
93
94 func validateConfiguration(configuration *config.Config) error {
95         if configuration.InfoProducerHost == "" {
96                 return fmt.Errorf("missing INFO_PRODUCER_HOST")
97         }
98         return nil
99 }
100
101 func registerTypesAndProducer(jobHandler jobs.JobTypeHandler, infoCoordinatorAddress string, callbackAddress string) error {
102         registrator := config.NewRegistratorImpl(infoCoordinatorAddress, retryClient)
103         if types, err := jobHandler.GetTypes(); err == nil {
104                 if regErr := registrator.RegisterTypes(types); regErr != nil {
105                         return fmt.Errorf("unable to register all types due to: %v", regErr)
106                 }
107         } else {
108                 return fmt.Errorf("unable to get types to register due to: %v", err)
109         }
110         producer := config.ProducerRegistrationInfo{
111                 InfoProducerSupervisionCallbackUrl: callbackAddress + server.StatusPath,
112                 SupportedInfoTypes:                 jobHandler.GetSupportedTypes(),
113                 InfoJobCallbackUrl:                 callbackAddress + server.AddJobPath,
114         }
115         if err := registrator.RegisterProducer("DMaaP_Mediator_Producer", &producer); err != nil {
116                 return fmt.Errorf("unable to register producer due to: %v", err)
117         }
118         return nil
119 }