fx/ingestor currencies map fixed

This commit is contained in:
Stephan D
2025-12-12 11:05:12 +01:00
parent 681d53e856
commit 17333df7af
26 changed files with 86 additions and 92 deletions

View File

@@ -214,16 +214,13 @@ func (c *cbrConnector) refreshDirectory() error {
var directory valuteDirectory
if err := decoder.Decode(&directory); err != nil {
c.logger.Warn(
"CBR directory decode failed",
zap.Error(err),
zap.String("endpoint", endpoint),
)
c.logger.Warn("CBR directory decode failed", zap.Error(err), zap.String("endpoint", endpoint))
return merrors.InternalWrap(err, "cbr: decode directory")
}
mapping, err := buildValuteMapping(directory.Items)
mapping, err := buildValuteMapping(c.logger.Named("mapper"), directory.Items)
if err != nil {
c.logger.Warn("Failed to build currencies mapping", zap.Error(err), zap.String("endpoint", endpoint))
return err
}
@@ -235,23 +232,22 @@ func (c *cbrConnector) refreshDirectory() error {
func (c *cbrConnector) fetchDailyRate(ctx context.Context, valute valuteInfo) (string, error) {
endpoint, err := c.buildURL(c.dailyPath, nil)
if err != nil {
c.logger.Warn("Failed to build daily fetch URL", zap.Error(err), zap.String("path", c.dailyPath))
return "", err
}
req, err := c.http.NewRequest(ctx, http.MethodGet, endpoint)
if err != nil {
c.logger.Warn("Failed to request daily rate", zap.Error(err), zap.String("endpoint", endpoint))
return "", merrors.InternalWrap(err, "cbr: build daily request")
}
resp, err := c.http.Do(req)
if err != nil {
c.logger.Warn(
"CBR daily request failed",
zap.String("currency", valute.ISOCharCode),
zap.String("endpoint", endpoint),
zap.String("referer", c.http.headerValue("Referer")),
c.logger.Warn("CBR daily request failed",
zap.Error(err), zap.String("currency", valute.ISOCharCode),
zap.String("endpoint", endpoint), zap.String("referer", c.http.headerValue("Referer")),
zap.String("user_agent", c.http.headerValue("User-Agent")),
zap.Error(err),
)
return "", merrors.InternalWrap(err, "cbr: daily request failed")
}
@@ -259,10 +255,8 @@ func (c *cbrConnector) fetchDailyRate(ctx context.Context, valute valuteInfo) (s
if resp.StatusCode != http.StatusOK {
c.logger.Warn(
"CBR daily returned non-OK status",
zap.Int("status", resp.StatusCode),
zap.String("currency", valute.ISOCharCode),
zap.String("endpoint", endpoint),
"CBR daily returned non-OK status", zap.Int("status", resp.StatusCode),
zap.String("currency", valute.ISOCharCode), zap.String("endpoint", endpoint),
)
return "", merrors.Internal("cbr: unexpected status " + strconv.Itoa(resp.StatusCode))
}
@@ -272,11 +266,8 @@ func (c *cbrConnector) fetchDailyRate(ctx context.Context, valute valuteInfo) (s
var payload dailyRates
if err := decoder.Decode(&payload); err != nil {
c.logger.Warn(
"CBR daily decode failed",
zap.String("currency", valute.ISOCharCode),
zap.String("endpoint", endpoint),
zap.Error(err),
c.logger.Warn("CBR daily decode failed", zap.Error(err),
zap.String("currency", valute.ISOCharCode), zap.String("endpoint", endpoint),
)
return "", merrors.InternalWrap(err, "cbr: decode daily response")
}
@@ -410,7 +401,7 @@ type valuteMapping struct {
byID map[string]valuteInfo
}
func buildValuteMapping(items []valuteItem) (*valuteMapping, error) {
func buildValuteMapping(logger *zap.Logger, items []valuteItem) (*valuteMapping, error) {
byISO := make(map[string]valuteInfo, len(items))
byID := make(map[string]valuteInfo, len(items))
byNum := make(map[string]string, len(items))
@@ -425,34 +416,35 @@ func buildValuteMapping(items []valuteItem) (*valuteMapping, error) {
if err != nil {
return nil, merrors.InvalidDataType("cbr: parse directory nominal: " + err.Error())
}
if id == "" || isoChar == "" {
return nil, merrors.InvalidDataType("cbr: directory contains entry with empty id or iso code")
}
info := valuteInfo{
ID: id,
ISOCharCode: isoChar,
ISONumCode: isoNum,
Name: name,
EngName: engName,
Nominal: nominal,
}
if existing, ok := byISO[isoChar]; ok && existing.ID != id {
return nil, merrors.InvalidDataType("cbr: duplicate ISO code " + isoChar)
}
if existing, ok := byID[id]; ok && existing.ISOCharCode != isoChar {
return nil, merrors.InvalidDataType("cbr: duplicate valute id " + id)
}
if isoNum != "" {
if existingID, ok := byNum[isoNum]; ok && existingID != id {
return nil, merrors.InvalidDataType("cbr: duplicate ISO numeric code " + isoNum)
if id != "" && isoChar != "" {
info := valuteInfo{
ID: id,
ISOCharCode: isoChar,
ISONumCode: isoNum,
Name: name,
EngName: engName,
Nominal: nominal,
}
byNum[isoNum] = id
}
byISO[isoChar] = info
byID[id] = info
if existing, ok := byISO[isoChar]; ok && existing.ID != id {
return nil, merrors.InvalidDataType("cbr: duplicate ISO code " + isoChar)
}
if existing, ok := byID[id]; ok && existing.ISOCharCode != isoChar {
return nil, merrors.InvalidDataType("cbr: duplicate valute id " + id)
}
if isoNum != "" {
if existingID, ok := byNum[isoNum]; ok && existingID != id {
return nil, merrors.InvalidDataType("cbr: duplicate ISO numeric code " + isoNum)
}
byNum[isoNum] = id
}
logger.Info("Installing currency code", zap.String("iso_code", isoChar), zap.String("id", id))
byISO[isoChar] = info
byID[id] = info
} else {
logger.Info("Skipping invalid currency entry", zap.String("id", id), zap.String("iso_char", isoChar))
}
}
if len(byISO) == 0 {