Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -92,6 +92,15 @@ func productSeriesFallbackEnabled() bool {
|
|||||||
return raw == "1" || raw == "true" || raw == "on" || raw == "yes"
|
return raw == "1" || raw == "true" || raw == "on" || raw == "yes"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func productSeriesFallbackAutoCreateEnabled() bool {
|
||||||
|
// Default on: avoid manual intervention by auto-creating the fallback dfgrp row when missing.
|
||||||
|
raw := strings.TrimSpace(strings.ToLower(os.Getenv("PRODUCT_SERIES_FALLBACK_AUTO_CREATE")))
|
||||||
|
if raw == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return raw == "1" || raw == "true" || raw == "on" || raw == "yes"
|
||||||
|
}
|
||||||
|
|
||||||
func productSeriesFallbackCode() string {
|
func productSeriesFallbackCode() string {
|
||||||
code := strings.TrimSpace(os.Getenv("PRODUCT_SERIES_FALLBACK_SERIES_CODE"))
|
code := strings.TrimSpace(os.Getenv("PRODUCT_SERIES_FALLBACK_SERIES_CODE"))
|
||||||
if code == "" {
|
if code == "" {
|
||||||
@@ -141,13 +150,61 @@ LIMIT 1
|
|||||||
`, code).Scan(&id, &gotCode)
|
`, code).Scan(&id, &gotCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
// cache negative for a short period too
|
if !productSeriesFallbackAutoCreateEnabled() {
|
||||||
|
// cache negative for a short period too
|
||||||
|
productSeriesFallbackMu.Lock()
|
||||||
|
productSeriesFallbackCachedCode = code
|
||||||
|
productSeriesFallbackCachedID = 0
|
||||||
|
productSeriesFallbackCachedAt = time.Now()
|
||||||
|
productSeriesFallbackMu.Unlock()
|
||||||
|
return 0, code, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-create the fallback series definition (best-effort) to avoid manual steps.
|
||||||
|
// We guard with the same mutex to avoid duplicate inserts within this process.
|
||||||
productSeriesFallbackMu.Lock()
|
productSeriesFallbackMu.Lock()
|
||||||
|
defer productSeriesFallbackMu.Unlock()
|
||||||
|
|
||||||
|
// Re-check under lock in case another goroutine created it while we were waiting.
|
||||||
|
if productSeriesFallbackCachedCode == code && productSeriesFallbackCachedID > 0 &&
|
||||||
|
productSeriesFallbackCachedAt.After(time.Now().Add(-10*time.Minute)) {
|
||||||
|
return productSeriesFallbackCachedID, code, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var createdID int64
|
||||||
|
createErr := pg.QueryRowContext(ctx, `
|
||||||
|
INSERT INTO dfgrp (code, title, is_active, typ, master, parent_filter, sort_order, is_required, notes)
|
||||||
|
SELECT $1, $1, TRUE, 'opt', 'zbggseri', '', 0, FALSE, 'auto-created fallback series'
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM dfgrp WHERE master='zbggseri' AND code=$1
|
||||||
|
)
|
||||||
|
RETURNING id
|
||||||
|
`, code).Scan(&createdID)
|
||||||
|
if createErr != nil {
|
||||||
|
// If RETURNING didn't return because it already exists, select it now.
|
||||||
|
var sid int64
|
||||||
|
var scode string
|
||||||
|
selErr := pg.QueryRowContext(ctx, `
|
||||||
|
SELECT id, COALESCE(code,'')
|
||||||
|
FROM dfgrp
|
||||||
|
WHERE master='zbggseri' AND code=$1
|
||||||
|
ORDER BY id
|
||||||
|
LIMIT 1
|
||||||
|
`, code).Scan(&sid, &scode)
|
||||||
|
if selErr != nil {
|
||||||
|
// still missing; treat as disabled for now
|
||||||
|
productSeriesFallbackCachedCode = code
|
||||||
|
productSeriesFallbackCachedID = 0
|
||||||
|
productSeriesFallbackCachedAt = time.Now()
|
||||||
|
return 0, code, nil
|
||||||
|
}
|
||||||
|
createdID = sid
|
||||||
|
}
|
||||||
|
|
||||||
productSeriesFallbackCachedCode = code
|
productSeriesFallbackCachedCode = code
|
||||||
productSeriesFallbackCachedID = 0
|
productSeriesFallbackCachedID = createdID
|
||||||
productSeriesFallbackCachedAt = time.Now()
|
productSeriesFallbackCachedAt = time.Now()
|
||||||
productSeriesFallbackMu.Unlock()
|
return createdID, code, nil
|
||||||
return 0, code, nil
|
|
||||||
}
|
}
|
||||||
return 0, code, err
|
return 0, code, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user