oneToOneReconciliation performs a one-to-one reconciliation, where each external transaction is matched against a single internal transaction. The process is parallelized using goroutines. Parameters: - ctx: Context for managing cancellation and timeouts. - externalTxns: The list of external transac
(ctx context.Context, externalTxns []*model.Transaction, matchingRules []model.MatchingRule)
| 620 | // - []model.Match: A list of matched transactions. |
| 621 | // - []string: A list of unmatched transaction IDs. |
| 622 | func (s *LedgerForge) oneToOneReconciliation(ctx context.Context, externalTxns []*model.Transaction, matchingRules []model.MatchingRule) ([]model.Match, []string) { |
| 623 | conf, err := config.Fetch() |
| 624 | if err != nil { |
| 625 | logrus.Errorf("Error fetching configuration: %v", err) |
| 626 | } |
| 627 | maxWorkers := 10 // Default |
| 628 | if conf != nil { |
| 629 | maxWorkers = conf.Transaction.MaxWorkers |
| 630 | } |
| 631 | |
| 632 | var matches []model.Match |
| 633 | var unmatched []string |
| 634 | |
| 635 | matchChan := make(chan model.Match, len(externalTxns)) // Channel to collect matched transactions. |
| 636 | unmatchedChan := make(chan string, len(externalTxns)) // Channel to collect unmatched transactions. |
| 637 | var wg sync.WaitGroup // WaitGroup to manage concurrent goroutines. |
| 638 | sem := make(chan struct{}, maxWorkers) // Semaphore to limit concurrency |
| 639 | |
| 640 | // Iterate over each external transaction and attempt to match it against internal transactions. |
| 641 | for _, externalTxn := range externalTxns { |
| 642 | wg.Add(1) |
| 643 | go func(extTxn *model.Transaction) { |
| 644 | defer wg.Done() |
| 645 | sem <- struct{}{} // Acquire token |
| 646 | defer func() { <-sem }() // Release token |
| 647 | |
| 648 | err := s.findMatchingInternalTransaction(ctx, extTxn, matchingRules, matchChan, unmatchedChan) |
| 649 | if err != nil { |
| 650 | unmatchedChan <- extTxn.TransactionID |
| 651 | logrus.Errorf("No match found for external transaction %s: %v", extTxn.TransactionID, err) |
| 652 | } |
| 653 | }(externalTxn) |
| 654 | } |
| 655 | |
| 656 | // Close the channels after all goroutines are finished. |
| 657 | go func() { |
| 658 | wg.Wait() |
| 659 | close(matchChan) |
| 660 | close(unmatchedChan) |
| 661 | }() |
| 662 | |
| 663 | // Collect matches and unmatched transactions from channels. |
| 664 | for match := range matchChan { |
| 665 | matches = append(matches, match) |
| 666 | } |
| 667 | for unmatchedID := range unmatchedChan { |
| 668 | unmatched = append(unmatched, unmatchedID) |
| 669 | } |
| 670 | |
| 671 | return matches, unmatched |
| 672 | } |
| 673 | |
| 674 | // oneToManyReconciliation performs a one-to-many reconciliation, where each external transaction can match |
| 675 | // multiple internal transactions grouped by specific criteria. |