Skip to content

Commit 9a310fe

Browse files
committed
Add a way to "sync" transitions only, by a query
1 parent c0291d3 commit 9a310fe

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

src/main/java/org/hibernate/infra/replicate/jira/service/jira/JiraService.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import java.util.concurrent.atomic.AtomicInteger;
1111
import java.util.concurrent.atomic.AtomicLong;
1212
import java.util.function.BooleanSupplier;
13+
import java.util.function.Consumer;
1314

1415
import org.hibernate.infra.replicate.jira.JiraConfig;
1516
import org.hibernate.infra.replicate.jira.service.jira.client.JiraRestClient;
1617
import org.hibernate.infra.replicate.jira.service.jira.client.JiraRestClientBuilder;
18+
import org.hibernate.infra.replicate.jira.service.jira.handler.JiraIssueTransitionOnlyEventHandler;
1719
import org.hibernate.infra.replicate.jira.service.jira.model.hook.JiraWebHookEvent;
1820
import org.hibernate.infra.replicate.jira.service.jira.model.hook.JiraWebHookIssue;
1921
import org.hibernate.infra.replicate.jira.service.jira.model.hook.JiraWebHookIssueLink;
@@ -154,6 +156,25 @@ public void registerManagementRoutes(@Observes ManagementInterface mi) {
154156
triggerSyncEvent(context.sourceJiraClient().getIssue(issue), context);
155157
rc.end();
156158
});
159+
mi.router().get("/sync/issues/transition/re-sync/:project").blockingHandler(rc -> {
160+
// TODO: we can remove this one once we figure out why POST management does not
161+
// work correctly...
162+
String project = rc.pathParam("project");
163+
String query = rc.queryParam("query").getFirst();
164+
165+
HandlerProjectContext context = contextPerProject.get(project);
166+
167+
if (context == null) {
168+
throw new IllegalArgumentException("Unknown project '%s'".formatted(project));
169+
}
170+
171+
context.submitTask(() -> {
172+
syncByQuery(query, context, jiraIssue -> {
173+
context.submitTask(new JiraIssueTransitionOnlyEventHandler(reportingConfig, context, jiraIssue));
174+
});
175+
});
176+
rc.end();
177+
});
157178
mi.router().post("/sync/issues/list").consumes(MediaType.APPLICATION_JSON).blockingHandler(rc -> {
158179
// sync issues based on a list of issue-keys supplied in the JSON body:
159180
JsonObject request = rc.body().asJsonObject();
@@ -272,12 +293,16 @@ public void finishProcessingAndShutdown() {
272293
}
273294

274295
private void syncByQuery(String query, HandlerProjectContext context) {
296+
syncByQuery(query, context, jiraIssue -> triggerSyncEvent(jiraIssue, context));
297+
}
298+
299+
private void syncByQuery(String query, HandlerProjectContext context, Consumer<JiraIssue> action) {
275300
JiraIssues issues = null;
276301
int start = 0;
277302
int max = 100;
278303
do {
279304
issues = context.sourceJiraClient().find(query, start, max);
280-
issues.issues.forEach(jiraIssue -> triggerSyncEvent(jiraIssue, context));
305+
issues.issues.forEach(action);
281306

282307
start += max;
283308
} while (!issues.issues.isEmpty());
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package org.hibernate.infra.replicate.jira.service.jira.handler;
2+
3+
import java.util.Optional;
4+
5+
import org.hibernate.infra.replicate.jira.service.jira.HandlerProjectContext;
6+
import org.hibernate.infra.replicate.jira.service.jira.client.JiraRestException;
7+
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraIssue;
8+
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraTransition;
9+
import org.hibernate.infra.replicate.jira.service.reporting.ReportingConfig;
10+
11+
public class JiraIssueTransitionOnlyEventHandler extends JiraEventHandler {
12+
13+
private final JiraIssue sourceIssue;
14+
15+
public JiraIssueTransitionOnlyEventHandler(ReportingConfig reportingConfig, HandlerProjectContext context,
16+
JiraIssue issue) {
17+
super(reportingConfig, context, issue.id);
18+
this.sourceIssue = issue;
19+
}
20+
21+
@Override
22+
protected void doRun() {
23+
// NOTE: we do not look up the source issue as we've already queried for it
24+
// before creating this handler:
25+
String destinationKey = toDestinationKey(sourceIssue.key);
26+
// We don't really need one, but doing so means that we will create the
27+
// placeholder for it if the issue wasn't already present in the destination
28+
// Jira instance
29+
context.createNextPlaceholderBatch(destinationKey);
30+
31+
try {
32+
// issue status can be updated only through transition:
33+
prepareTransition(sourceIssue).ifPresent(
34+
jiraTransition -> context.destinationJiraClient().transition(destinationKey, jiraTransition));
35+
} catch (JiraRestException e) {
36+
failureCollector
37+
.critical("Unable to update destination issue %s: %s".formatted(destinationKey, e.getMessage()), e);
38+
}
39+
}
40+
41+
@Override
42+
public String toString() {
43+
return "JiraIssueTransitionOnlyEventHandler[" + "objectId=" + objectId + ", project=" + context.projectName()
44+
+ ']';
45+
}
46+
47+
private Optional<JiraTransition> prepareTransition(JiraIssue sourceIssue) {
48+
return statusToTransition(sourceIssue.fields.status.id).map(
49+
tr -> new JiraTransition(tr, "Upstream issue status updated to: " + sourceIssue.fields.status.name));
50+
}
51+
52+
}

0 commit comments

Comments
 (0)