diff --git a/csharp/Platform.Bot/Program.cs b/csharp/Platform.Bot/Program.cs index 521a6b95..977273a1 100644 --- a/csharp/Platform.Bot/Program.cs +++ b/csharp/Platform.Bot/Program.cs @@ -71,7 +71,7 @@ private static async Task Main(string[] args) var minimumInteractionIntervalOption = new Option( name: "--minimum-interaction-interval", description: "Minimum interaction interval in seconds.", - getDefaultValue: () => 60); + getDefaultValue: () => 300); var rootCommand = new RootCommand("Sample app for System.CommandLine") { diff --git a/csharp/Platform.Bot/Trackers/IssueTracker.cs b/csharp/Platform.Bot/Trackers/IssueTracker.cs index 1c53a4c9..0ad2b262 100644 --- a/csharp/Platform.Bot/Trackers/IssueTracker.cs +++ b/csharp/Platform.Bot/Trackers/IssueTracker.cs @@ -31,6 +31,14 @@ public class IssueTracker : ITracker /// private IList> _triggers { get; } + /// + /// + /// Tracks processed issues to prevent duplicate actions. + /// + /// + /// + private HashSet _processedIssues { get; } = new HashSet(); + /// /// /// Initializes a new instance. @@ -66,6 +74,15 @@ public async Task Start(CancellationToken cancellationToken) var allIssues = _storage.GetIssues(); foreach (var issue in allIssues) { + // Create a unique key for each issue-trigger combination to prevent duplicate processing + var issueKey = $"{issue.Repository.FullName}#{issue.Number}"; + + // Skip if this issue has already been processed + if (_processedIssues.Contains(issueKey)) + { + continue; + } + foreach (var trigger in _triggers) { if (cancellationToken.IsCancellationRequested) @@ -75,6 +92,9 @@ public async Task Start(CancellationToken cancellationToken) if (await trigger.Condition(issue)) { await trigger.Action(issue); + // Mark issue as processed after successful action + _processedIssues.Add(issueKey); + break; // Only process one trigger per issue to prevent conflicts } } } diff --git a/csharp/Platform.Bot/Trackers/PullRequestTracker.cs b/csharp/Platform.Bot/Trackers/PullRequestTracker.cs index 47287ee1..ec180492 100644 --- a/csharp/Platform.Bot/Trackers/PullRequestTracker.cs +++ b/csharp/Platform.Bot/Trackers/PullRequestTracker.cs @@ -33,6 +33,14 @@ public class PullRequestTracker : ITracker /// private IList> _triggers; + /// + /// + /// Tracks processed pull requests to prevent duplicate actions. + /// + /// + /// + private HashSet _processedPullRequests = new HashSet(); + /// /// /// Initializes a new instance. @@ -75,10 +83,22 @@ public async Task Start(CancellationToken cancellationToken) { return; } + + // Create a unique key for each pull request to prevent duplicate processing + var pullRequestKey = $"{repository.FullName}#{pullRequest.Number}"; + + // Skip if this pull request has already been processed + if (_processedPullRequests.Contains(pullRequestKey)) + { + continue; + } + var detailedPullRequest = _storage.Client.PullRequest.Get(repository.Id, pullRequest.Number).AwaitResult(); if (await trigger.Condition(detailedPullRequest)) { await trigger.Action(detailedPullRequest); + // Mark pull request as processed after successful action + _processedPullRequests.Add(pullRequestKey); } } } diff --git a/csharp/Storage/RemoteStorage/GitHubStorage.cs b/csharp/Storage/RemoteStorage/GitHubStorage.cs index 888a7426..7c8c7f51 100644 --- a/csharp/Storage/RemoteStorage/GitHubStorage.cs +++ b/csharp/Storage/RemoteStorage/GitHubStorage.cs @@ -103,12 +103,21 @@ public IReadOnlyList GetIssues() Since = lastIssue }; var issues = Client.Issue.GetAllForCurrent(request).Result; + + // Always update lastIssue to current time to prevent reprocessing the same timeframe + // even when there are no new issues + var now = DateTimeOffset.Now; if (issues.Count != 0) { - lastIssue = issues.Max(x => x.CreatedAt); - return issues; + var maxIssueTime = issues.Max(x => x.CreatedAt); + lastIssue = maxIssueTime > now ? maxIssueTime : now; } - return new List(); + else + { + lastIssue = now; + } + + return issues; } public Task> GetCommits(long repositoryId, CommitRequest commitRequest) => Client.Repository.Commit.GetAll(repositoryId, commitRequest);