contractNoticeID duplication fix
This commit is contained in:
@@ -575,10 +575,16 @@ func (w *NoticeWorker) ToTender(n *notice.Notice) (*tender.Tender, error) {
|
|||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolveExistingTender finds the tender that this notice should update, preferring the procedure-level
|
// resolveExistingTender finds the tender that this notice should update. TED ContractNoticeID uniquely
|
||||||
// ContractFolderID (so follow-up notices like a Result for an earlier Competition notice merge into the
|
// identifies the notice document; try it first so we never open a second tender row for the same notice.
|
||||||
// same tender), then UBL ProcurementProject/ID (merges per-lot CAN/CN notices), then NoticePublicationID.
|
// Then procedure-level ContractFolderID (follow-up notices merge), UBL ProcurementProject/ID (per-lot),
|
||||||
|
// then NoticePublicationID.
|
||||||
func (w *NoticeWorker) resolveExistingTender(ctx context.Context, n *notice.Notice) *tender.Tender {
|
func (w *NoticeWorker) resolveExistingTender(ctx context.Context, n *notice.Notice) *tender.Tender {
|
||||||
|
if strings.TrimSpace(n.ContractNoticeID) != "" {
|
||||||
|
if t, err := w.TenderRepo.GetByContractNoticeID(ctx, n.ContractNoticeID); err == nil && t != nil {
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
}
|
||||||
if strings.TrimSpace(n.ContractFolderID) != "" {
|
if strings.TrimSpace(n.ContractFolderID) != "" {
|
||||||
if t, err := w.TenderRepo.GetByContractFolderID(ctx, n.ContractFolderID); err == nil && t != nil {
|
if t, err := w.TenderRepo.GetByContractFolderID(ctx, n.ContractFolderID); err == nil && t != nil {
|
||||||
return t
|
return t
|
||||||
@@ -998,7 +1004,7 @@ func (w *NoticeWorker) persistTender(ctx context.Context, t *tender.Tender, n *n
|
|||||||
lastErr = err
|
lastErr = err
|
||||||
|
|
||||||
// Another goroutine inserted the same procedure/publication first: merge into the winner row.
|
// Another goroutine inserted the same procedure/publication first: merge into the winner row.
|
||||||
if isDuplicateKeyError(err) && (isDuplicateTenderBusinessKeyError(err) || isDuplicateContractFolderIDKeyError(err) || isDuplicateProcurementProjectIDKeyError(err)) {
|
if isDuplicateKeyError(err) && (isDuplicateTenderBusinessKeyError(err) || isDuplicateContractNoticeIDKeyError(err) || isDuplicateContractFolderIDKeyError(err) || isDuplicateProcurementProjectIDKeyError(err)) {
|
||||||
tMerged, convErr := w.ToTender(n)
|
tMerged, convErr := w.ToTender(n)
|
||||||
if convErr != nil {
|
if convErr != nil {
|
||||||
return convErr
|
return convErr
|
||||||
@@ -1062,6 +1068,13 @@ func isDuplicateTenderBusinessKeyError(err error) bool {
|
|||||||
return strings.Contains(msg, "notice_publication_id")
|
return strings.Contains(msg, "notice_publication_id")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isDuplicateContractNoticeIDKeyError(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return strings.Contains(err.Error(), "contract_notice_id")
|
||||||
|
}
|
||||||
|
|
||||||
func isDuplicateContractFolderIDKeyError(err error) bool {
|
func isDuplicateContractFolderIDKeyError(err error) bool {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ func NewRepository(mongoManager *orm.ConnectionManager, logger logger.Logger) Te
|
|||||||
*orm.CreateUniqueIndex("tender_id_idx", bson.D{{Key: "tender_id", Value: 1}}),
|
*orm.CreateUniqueIndex("tender_id_idx", bson.D{{Key: "tender_id", Value: 1}}),
|
||||||
*orm.NewIndex("project_name_idx", bson.D{{Key: "project_name", Value: 1}}),
|
*orm.NewIndex("project_name_idx", bson.D{{Key: "project_name", Value: 1}}),
|
||||||
*orm.NewIndex("contract_notice_id_idx", bson.D{{Key: "contract_notice_id", Value: 1}}),
|
*orm.NewIndex("contract_notice_id_idx", bson.D{{Key: "contract_notice_id", Value: 1}}),
|
||||||
|
// One tender row per TED ContractNoticeID when present (parallel ingest / lookup gaps).
|
||||||
|
*orm.CreateUniqueIndex("contract_notice_id_unique", bson.D{{Key: "contract_notice_id", Value: 1}}).
|
||||||
|
WithPartialFilterExpression(bson.M{"contract_notice_id": bson.M{"$type": "string", "$ne": ""}}),
|
||||||
*orm.NewIndex("contract_folder_id_idx", bson.D{{Key: "contract_folder_id", Value: 1}}),
|
*orm.NewIndex("contract_folder_id_idx", bson.D{{Key: "contract_folder_id", Value: 1}}),
|
||||||
// One tender row per TED publication / procedure when ids are present (prevents parallel worker races).
|
// One tender row per TED publication / procedure when ids are present (prevents parallel worker races).
|
||||||
*orm.CreateUniqueIndex("notice_publication_id_unique", bson.D{{Key: "notice_publication_id", Value: 1}}).
|
*orm.CreateUniqueIndex("notice_publication_id_unique", bson.D{{Key: "notice_publication_id", Value: 1}}).
|
||||||
|
|||||||
Reference in New Issue
Block a user