diff --git a/config/apis.go b/config/apis.go index c1f959405..98b1f6893 100644 --- a/config/apis.go +++ b/config/apis.go @@ -356,6 +356,12 @@ func storeDiffSection(ctx *context.Context, section string, db ConfigDB, v1, v2 return } return db.SetSection(ctx, section, diffLoggerJsonCfg(jsn, v1.LoggerCfg(), v2.LoggerCfg())) + case EFsJSON: + jsn := new(EfsJsonCfg) + if err = db.GetSection(ctx, section, jsn); err != nil { + return + } + return db.SetSection(ctx, section, diffEFsJsonCfg(jsn, v1.EFsCfg(), v1.EFsCfg())) case RPCConnsJSON: jsn := make(RPCConnsJson) if err = db.GetSection(ctx, section, &jsn); err != nil { diff --git a/config/config.go b/config/config.go index bf8d276ec..d0e5b359d 100644 --- a/config/config.go +++ b/config/config.go @@ -234,6 +234,7 @@ func newCGRConfig(config []byte) (cfg *CGRConfig, err error) { IntervalStart: []*utils.DynamicDecimalBigOpt{}, ProfileIgnoreFilters: []*utils.DynamicBoolOpt{}, }}, + efsCfg: new(EFsCfg), actionSCfg: &ActionSCfg{Opts: &ActionsOpts{ ProfileIDs: []*utils.DynamicStringSliceOpt{}, ProfileIgnoreFilters: []*utils.DynamicBoolOpt{}, @@ -353,6 +354,7 @@ type CGRConfig struct { admS *AdminSCfg // APIer config ersCfg *ERsCfg // EventReader config eesCfg *EEsCfg // EventExporter config + efsCfg *EFsCfg // EventFailover config rateSCfg *RateSCfg // RateS config actionSCfg *ActionSCfg // ActionS config sipAgentCfg *SIPAgentCfg // SIPAgent config @@ -628,6 +630,13 @@ func (cfg *CGRConfig) ListenCfg() *ListenCfg { return cfg.listenCfg } +// EFsCfg returns the export failover config +func (cfg *CGRConfig) EFsCfg() *EFsCfg { + cfg.lks[EFsJSON].Lock() + defer cfg.lks[EFsJSON].Unlock() + return cfg.efsCfg +} + // HTTPCfg returns the config for HTTP func (cfg *CGRConfig) HTTPCfg() *HTTPCfg { cfg.lks[HTTPJSON].Lock() @@ -1039,6 +1048,7 @@ func (cfg *CGRConfig) Clone() (cln *CGRConfig) { admS: cfg.admS.Clone(), ersCfg: cfg.ersCfg.Clone(), eesCfg: cfg.eesCfg.Clone(), + efsCfg: cfg.efsCfg.Clone(), rateSCfg: cfg.rateSCfg.Clone(), sipAgentCfg: cfg.sipAgentCfg.Clone(), configSCfg: cfg.configSCfg.Clone(), diff --git a/config/config_json.go b/config/config_json.go index 25135f1ba..adb63d1c8 100644 --- a/config/config_json.go +++ b/config/config_json.go @@ -46,6 +46,7 @@ const ( StatSJSON = "stats" ThresholdSJSON = "thresholds" TPeSJSON = "tpes" + EFsJSON = "efs" RouteSJSON = "routes" LoaderSJSON = "loaders" SureTaxJSON = "suretax" @@ -97,6 +98,7 @@ var ( DispatcherSJSON: utils.DispatcherS, DataDBJSON: utils.DataDB, EEsJSON: utils.EEs, + EFsJSON: utils.EFs, RateSJSON: utils.RateS, SIPAgentJSON: utils.SIPAgent, RegistrarCJSON: utils.RegistrarC, @@ -152,6 +154,7 @@ func newSections(cfg *CGRConfig) Sections { return Sections{ cfg.generalCfg, cfg.loggerCfg, + cfg.efsCfg, cfg.rpcConns, cfg.dataDbCfg, cfg.listenCfg, diff --git a/config/efs.go b/config/efs.go new file mode 100644 index 000000000..459095058 --- /dev/null +++ b/config/efs.go @@ -0,0 +1,115 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package config + +import ( + "time" + + "github.com/cgrates/birpc/context" + "github.com/cgrates/cgrates/utils" +) + +type EFsCfg struct { + Enabled bool + PosterAttempts int // Time to wait before writing the failed posts in a single file + FailedPostsDir string // Directory path where we store failed http requests + FailedPostsTTL time.Duration // Directory path where we store failed http requests +} + +func (EFsCfg) SName() string { return EFsJSON } + +func (efsCfg *EFsCfg) Load(ctx *context.Context, jsnCfg ConfigDB, _ *CGRConfig) (err error) { + jsonEFsCfg := new(EfsJsonCfg) + if err = jsnCfg.GetSection(ctx, EFsJSON, jsonEFsCfg); err != nil { + return + } + return efsCfg.loadFromJSONCfg(jsonEFsCfg) +} + +// loadFromJSONCfg loads EFs config from JsonCfg +func (efsCfg *EFsCfg) loadFromJSONCfg(jsonEFsCfg *EfsJsonCfg) (err error) { + if jsonEFsCfg == nil { + return + } + if jsonEFsCfg.Enabled != nil { + efsCfg.Enabled = *jsonEFsCfg.Enabled + } + if jsonEFsCfg.Poster_attempts != nil { + efsCfg.PosterAttempts = *jsonEFsCfg.Poster_attempts + } + if jsonEFsCfg.Failed_posts_dir != nil { + efsCfg.FailedPostsDir = *jsonEFsCfg.Failed_posts_dir + } + if jsonEFsCfg.Failed_posts_ttl != nil { + if efsCfg.FailedPostsTTL, err = utils.ParseDurationWithNanosecs(*jsonEFsCfg.Failed_posts_ttl); err != nil { + return + } + } + return +} + +// AsMapInterface returns the config of EFsCfg as a map[string]interface{} +func (efsCfg EFsCfg) AsMapInterface(string) interface{} { + mp := map[string]interface{}{ + utils.EnabledCfg: efsCfg.Enabled, + utils.FailedPostsDirCfg: efsCfg.FailedPostsDir, + utils.PosterAttemptsCfg: efsCfg.PosterAttempts, + } + if efsCfg.FailedPostsTTL != 0 { + mp[utils.FailedPostsTTLCfg] = efsCfg.FailedPostsTTL.String() + } + return mp +} + +func (efsCfg EFsCfg) CloneSection() Section { return efsCfg.Clone() } + +func (efsCfg EFsCfg) Clone() *EFsCfg { + return &EFsCfg{ + Enabled: efsCfg.Enabled, + PosterAttempts: efsCfg.PosterAttempts, + FailedPostsDir: efsCfg.FailedPostsDir, + FailedPostsTTL: efsCfg.FailedPostsTTL, + } +} + +type EfsJsonCfg struct { + Enabled *bool + Poster_attempts *int + Failed_posts_dir *string + Failed_posts_ttl *string +} + +func diffEFsJsonCfg(d *EfsJsonCfg, v1, v2 *EFsCfg) *EfsJsonCfg { + if d == nil { + return new(EfsJsonCfg) + } + if v1.Enabled != v2.Enabled { + d.Enabled = utils.BoolPointer(v2.Enabled) + } + if v1.PosterAttempts != v2.PosterAttempts { + d.Poster_attempts = utils.IntPointer(v2.PosterAttempts) + } + if v1.FailedPostsDir != v2.FailedPostsDir { + d.Failed_posts_dir = utils.StringPointer(v2.FailedPostsDir) + } + if v1.FailedPostsTTL != v2.FailedPostsTTL { + d.Failed_posts_ttl = utils.StringPointer(v2.FailedPostsTTL.String()) + } + return d +} diff --git a/config/generalcfg.go b/config/generalcfg.go index 164de4ee5..03a41280b 100644 --- a/config/generalcfg.go +++ b/config/generalcfg.go @@ -63,7 +63,6 @@ type GeneralCfg struct { Opts *GeneralOpts } -// loadGeneralCfg loads the General section of the configuration func (gencfg *GeneralCfg) Load(ctx *context.Context, jsnCfg ConfigDB, _ *CGRConfig) (err error) { jsnGeneralCfg := new(GeneralJsonCfg) if err = jsnCfg.GetSection(ctx, GeneralJSON, jsnGeneralCfg); err != nil { @@ -72,6 +71,7 @@ func (gencfg *GeneralCfg) Load(ctx *context.Context, jsnCfg ConfigDB, _ *CGRConf return gencfg.loadFromJSONCfg(jsnGeneralCfg) } +// loadGeneralCfg loads the General opts section of the configuration func (generalOpts *GeneralOpts) loadFromJSONCfg(jsnCfg *GeneralOptsJson) { if jsnCfg == nil { return