From 83de4ec348e870ae997bcc2fe0ee5c49f126c94d Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Thu, 17 Oct 2024 15:36:07 +0200 Subject: [PATCH 1/8] Add a simple dependabot configuration --- .github/dependabot.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8fd4800 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,23 @@ +version: 2 +updates: + - package-ecosystem: maven + directory: "/" + schedule: + interval: weekly + groups: + maven-plugins: + patterns: + - "*maven*plugin*" + - "org.apache.maven*:*" + exclude-patterns: + - "io.quarkus*" + quarkus: + patterns: + - "io.quarkus:*" + - "io.quarkus.*:*" + - "io.quarkiverse:*" + - "io.quarkiverse.*:*" + ignore: + # Releases too often, it's annoying + - dependency-name: "org.assertj:*" + update-types: ["version-update:semver-patch"] From d1576db510060e0a80a7a13044c5e0d8d7535ee9 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Thu, 17 Oct 2024 15:53:23 +0200 Subject: [PATCH 2/8] Move processing queue to group context since each group can have its own processing limits, and if we block the executor with pending tasks for one group, other group won't be able to get processed, while actually it could --- .../infra/replicate/jira/JiraConfig.java | 35 ++++++++++++---- .../replicate/jira/ProcessingConfig.java | 23 ---------- .../service/jira/HandlerProjectContext.java | 8 ++++ .../jira/HandlerProjectGroupContext.java | 38 +++++++++++++++-- .../jira/service/jira/JiraService.java | 42 +++++-------------- src/main/resources/application.properties | 5 +-- 6 files changed, 83 insertions(+), 68 deletions(-) delete mode 100644 src/main/java/org/hibernate/infra/replicate/jira/ProcessingConfig.java diff --git a/src/main/java/org/hibernate/infra/replicate/jira/JiraConfig.java b/src/main/java/org/hibernate/infra/replicate/jira/JiraConfig.java index bb0a1ff..de0bda3 100644 --- a/src/main/java/org/hibernate/infra/replicate/jira/JiraConfig.java +++ b/src/main/java/org/hibernate/infra/replicate/jira/JiraConfig.java @@ -94,6 +94,24 @@ interface JiraProjectGroup { } interface EventProcessing { + + /** + * Define how many events can be acknowledged and put on the pending queue + * before acknowledging an event results in blocking the response and waiting + * for the queue to free some space. + */ + @WithDefault("10000") + int queueSize(); + + /** + * Define the number of threads to use when processing queued events. + *

+ * Note, having a lot of processing threads might not bring much benefit as + * processing may also be limited by {@link JiraConfig.EventProcessing} + */ + @WithDefault("2") + int threads(); + /** * Defines how many events can be processed within the * {@link #timeframeInSeconds() timeframe} @@ -127,20 +145,20 @@ interface Scheduled { interface JiraProject { /** - * Downstream project id (not a project key!). - * Use {@code rest/api/2/project/YOUR-PROJECT-ID} to get the info. + * Downstream project id (not a project key!). Use + * {@code rest/api/2/project/YOUR-PROJECT-ID} to get the info. */ String projectId(); /** - * Downstream project key. - * Use {@code rest/api/2/project/YOUR-PROJECT-ID} to get the info. + * Downstream project key. Use {@code rest/api/2/project/YOUR-PROJECT-ID} to get + * the info. */ String projectKey(); /** - * Upstream project key. - * Use {@code rest/api/2/project/YOUR-PROJECT-ID} to get the info. + * Upstream project key. Use {@code rest/api/2/project/YOUR-PROJECT-ID} to get + * the info. */ String originalProjectKey(); @@ -154,8 +172,9 @@ interface WebHookSecurity { /** * Whether to enable signature verification. *

- * Jira web hooks can send a {@code x-hub-signature} header with a signature of a request body. - * This signature can be then verified using the secret used to configure the web hook. + * Jira web hooks can send a {@code x-hub-signature} header with a signature of + * a request body. This signature can be then verified using the secret used to + * configure the web hook. */ @WithDefault("false") boolean enabled(); diff --git a/src/main/java/org/hibernate/infra/replicate/jira/ProcessingConfig.java b/src/main/java/org/hibernate/infra/replicate/jira/ProcessingConfig.java deleted file mode 100644 index f29b7f5..0000000 --- a/src/main/java/org/hibernate/infra/replicate/jira/ProcessingConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.hibernate.infra.replicate.jira; - -import io.smallrye.config.ConfigMapping; -import io.smallrye.config.WithDefault; - -@ConfigMapping(prefix = "processing.events") -public interface ProcessingConfig { - /** - * Define how many events can be acknowledged and put on the pending queue before - * acknowledging an event results in blocking the response and waiting for the queue to free some space. - */ - @WithDefault("10000") - int queueSize(); - - /** - * Define the number of threads to use when processing queued events. - *

- * Note, having a lot of processing threads might not bring much benefit as processing - * may also be limited by {@link JiraConfig.EventProcessing} - */ - @WithDefault("2") - int threads(); -} diff --git a/src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectContext.java b/src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectContext.java index bb603a1..e9d1bef 100644 --- a/src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectContext.java +++ b/src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectContext.java @@ -183,4 +183,12 @@ public String toString() { public void close() { projectGroupContext.close(); } + + public int pendingEventsInCurrentContext() { + return projectGroupContext.pendingEventsInCurrentContext(); + } + + public void submitTask(Runnable runnable) { + projectGroupContext.submitTask(runnable); + } } diff --git a/src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectGroupContext.java b/src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectGroupContext.java index 3f78495..5c85030 100644 --- a/src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectGroupContext.java +++ b/src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectGroupContext.java @@ -1,14 +1,22 @@ package org.hibernate.infra.replicate.jira.service.jira; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.Semaphore; +import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; import org.hibernate.infra.replicate.jira.JiraConfig; +import io.quarkus.logging.Log; + public final class HandlerProjectGroupContext implements AutoCloseable { + private final ExecutorService eventHandlingExecutor; + private final Supplier workQueueSize; private final ScheduledExecutorService rateLimiterExecutor = Executors.newScheduledThreadPool(1); private final Semaphore rateLimiter; private final JiraConfig.JiraProjectGroup projectGroup; @@ -16,13 +24,19 @@ public final class HandlerProjectGroupContext implements AutoCloseable { public HandlerProjectGroupContext(JiraConfig.JiraProjectGroup projectGroup) { this.projectGroup = projectGroup; - final int permits = projectGroup.processing().eventsPerTimeframe(); + JiraConfig.EventProcessing processing = projectGroup.processing(); + + final int permits = processing.eventsPerTimeframe(); this.rateLimiter = new Semaphore(permits); rateLimiterExecutor.scheduleAtFixedRate(() -> { rateLimiter.drainPermits(); rateLimiter.release(permits); - }, projectGroup.processing().timeframeInSeconds(), projectGroup.processing().timeframeInSeconds(), - TimeUnit.SECONDS); + }, processing.timeframeInSeconds(), processing.timeframeInSeconds(), TimeUnit.SECONDS); + + LinkedBlockingDeque workQueue = new LinkedBlockingDeque<>(processing.queueSize()); + workQueueSize = workQueue::size; + eventHandlingExecutor = new ThreadPoolExecutor(processing.threads(), processing.threads(), 0L, + TimeUnit.MILLISECONDS, workQueue); } public void startProcessingEvent() throws InterruptedException { @@ -33,6 +47,14 @@ public JiraConfig.JiraProjectGroup projectGroup() { return projectGroup; } + public int pendingEventsInCurrentContext() { + return workQueueSize.get(); + } + + public void submitTask(Runnable task) { + eventHandlingExecutor.submit(task); + } + @Override public void close() { // when requesting to close the context we aren't expecting to process any other @@ -40,5 +62,15 @@ public void close() { if (!rateLimiterExecutor.isShutdown()) { rateLimiterExecutor.shutdownNow(); } + if (!eventHandlingExecutor.isShutdown()) { + try { + eventHandlingExecutor.shutdown(); + if (!eventHandlingExecutor.awaitTermination(2, TimeUnit.MINUTES)) { + Log.warnf("Not all events were processed before the shutdown"); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } } } diff --git a/src/main/java/org/hibernate/infra/replicate/jira/service/jira/JiraService.java b/src/main/java/org/hibernate/infra/replicate/jira/service/jira/JiraService.java index 0c8db5b..ae15f0c 100644 --- a/src/main/java/org/hibernate/infra/replicate/jira/service/jira/JiraService.java +++ b/src/main/java/org/hibernate/infra/replicate/jira/service/jira/JiraService.java @@ -7,15 +7,9 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Supplier; import org.hibernate.infra.replicate.jira.JiraConfig; -import org.hibernate.infra.replicate.jira.ProcessingConfig; import org.hibernate.infra.replicate.jira.service.jira.client.JiraRestClient; import org.hibernate.infra.replicate.jira.service.jira.client.JiraRestClientBuilder; import org.hibernate.infra.replicate.jira.service.jira.model.hook.JiraWebHookEvent; @@ -47,19 +41,12 @@ public class JiraService { private final ReportingConfig reportingConfig; - private final ExecutorService executor; - private final Supplier workQueueSize; private final Map contextPerProject; private final JiraConfig jiraConfig; private final Scheduler scheduler; @Inject - public JiraService(ProcessingConfig processingConfig, JiraConfig jiraConfig, ReportingConfig reportingConfig, - Scheduler scheduler) { - LinkedBlockingDeque workQueue = new LinkedBlockingDeque<>(processingConfig.queueSize()); - workQueueSize = workQueue::size; - executor = new ThreadPoolExecutor(processingConfig.threads(), processingConfig.threads(), 0L, - TimeUnit.MILLISECONDS, workQueue); + public JiraService(JiraConfig jiraConfig, ReportingConfig reportingConfig, Scheduler scheduler) { Map contextMap = new HashMap<>(); for (var entry : jiraConfig.projectGroup().entrySet()) { @@ -158,7 +145,7 @@ public void registerManagementRoutes(@Observes ManagementInterface mi) { throw new IllegalArgumentException("Unknown project '%s'".formatted(project)); } - executor.submit(() -> { + context.submitTask(() -> { for (String issueKey : issueKeys) { triggerSyncEvent(context.sourceJiraClient().getIssue(issueKey), context); } @@ -176,7 +163,7 @@ public void registerManagementRoutes(@Observes ManagementInterface mi) { throw new IllegalArgumentException("Unknown project '%s'".formatted(project)); } - executor.submit(() -> syncByQuery(query, context)); + context.submitTask(() -> syncByQuery(query, context)); rc.end(); }); mi.router().post("/sync/comments/list").consumes(MediaType.APPLICATION_JSON).blockingHandler(rc -> { @@ -223,7 +210,7 @@ public void acknowledge(String project, JiraWebHookEvent event) { } for (Runnable handler : eventType.handlers(reportingConfig, event, context)) { - executor.submit(handler); + context.submitTask(handler); } }, () -> Log.infof("Event type %s is not supported and cannot be handled.", event.webhookEvent)); } @@ -254,20 +241,12 @@ public void syncLastUpdated(String projectGroup) { @PreDestroy public void finishProcessingAndShutdown() { - try { - executor.shutdown(); - if (!executor.awaitTermination(2, TimeUnit.MINUTES)) { - Log.infof("Not all events were processed before the shutdown"); + for (HandlerProjectContext context : contextPerProject.values()) { + try { + context.close(); + } catch (Exception e) { + Log.errorf(e, "Error closing context %s: %s", context, e.getMessage()); } - for (HandlerProjectContext context : contextPerProject.values()) { - try { - context.close(); - } catch (Exception e) { - Log.errorf(e, "Error closing context %s: %s", context, e.getMessage()); - } - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); } } @@ -285,7 +264,8 @@ private void syncByQuery(String query, HandlerProjectContext context) { private void triggerSyncEvent(JiraIssue jiraIssue, HandlerProjectContext context) { Log.infof("Adding sync events for a jira issue: %s; Already queued events: %s", jiraIssue.key, - workQueueSize.get()); + context.pendingEventsInCurrentContext()); + JiraWebHookIssue issue = new JiraWebHookIssue(); issue.id = jiraIssue.id; issue.key = jiraIssue.key; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 10e05f9..a65de24 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -15,6 +15,8 @@ jira.project-group."hibernate".destination.login-kind=BEARER_TOKEN jira.project-group."hibernate".destination.api-user.email=${JIRA_API_USER_REDHAT} jira.project-group."hibernate".destination.api-user.token=${JIRA_API_TOKEN_REDHAT} jira.project-group."hibernate".can-set-reporter=true +# Processing queue configuration: +jira.project-group."hibernate".processing.queue-size=${PROCESSING_QUEUE_SIZE:10000} # # Management endpoints: quarkus.management.enabled=true @@ -29,9 +31,6 @@ quarkus.security.users.embedded.enabled=true quarkus.security.users.embedded.plain-text=true quarkus.security.users.embedded.users."management-user"=${MANAGEMENT_USER_PASSWORD} # -# Processing queue configuration: -processing.events.queue-size=${PROCESSING_QUEUE_SIZE:1000} -# # Scheduler: # >> By default, the scheduler is not started unless a @Scheduled business method is found. # >> You may need to force the start of the scheduler for "pure" programmatic scheduling via quarkus.scheduler.start-mode=forced From 59a5a9ca8982a77dccbc1161cede9128ce6e2f37 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:37:00 +0000 Subject: [PATCH 3/8] Bump the maven-plugins group with 2 updates Bumps the maven-plugins group with 2 updates: [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) and [org.apache.maven.plugins:maven-failsafe-plugin](https://github.com/apache/maven-surefire). Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.3.1 to 3.5.1 - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.1...surefire-3.5.1) Updates `org.apache.maven.plugins:maven-failsafe-plugin` from 3.3.1 to 3.5.1 - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.1...surefire-3.5.1) Updates `org.apache.maven.plugins:maven-failsafe-plugin` from 3.3.1 to 3.5.1 - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.1...surefire-3.5.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven-plugins - dependency-name: org.apache.maven.plugins:maven-failsafe-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven-plugins - dependency-name: org.apache.maven.plugins:maven-failsafe-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven-plugins ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5f9cec4..8773ecd 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ 1.11.0 3.26.0 true - 3.3.1 + 3.5.1 2.43.0 apply 1.2.4 From 9d6ff019b6912f850b71c3e34dca99c57cbd7762 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:37:13 +0000 Subject: [PATCH 4/8] Bump the quarkus group with 3 updates Bumps the quarkus group with 3 updates: [io.quarkus.platform:quarkus-bom](https://github.com/quarkusio/quarkus-platform), [io.quarkus.platform:quarkus-maven-plugin](https://github.com/quarkusio/quarkus-platform) and [io.quarkiverse.helm:quarkus-helm](https://github.com/quarkiverse/quarkus-helm). Updates `io.quarkus.platform:quarkus-bom` from 3.14.3 to 3.15.1 - [Commits](https://github.com/quarkusio/quarkus-platform/compare/3.14.3...3.15.1) Updates `io.quarkus.platform:quarkus-maven-plugin` from 3.14.3 to 3.15.1 - [Commits](https://github.com/quarkusio/quarkus-platform/compare/3.14.3...3.15.1) Updates `io.quarkiverse.helm:quarkus-helm` from 1.2.4 to 1.2.5 - [Release notes](https://github.com/quarkiverse/quarkus-helm/releases) - [Commits](https://github.com/quarkiverse/quarkus-helm/compare/1.2.4...1.2.5) Updates `io.quarkus.platform:quarkus-maven-plugin` from 3.14.3 to 3.15.1 - [Commits](https://github.com/quarkusio/quarkus-platform/compare/3.14.3...3.15.1) --- updated-dependencies: - dependency-name: io.quarkus.platform:quarkus-bom dependency-type: direct:production update-type: version-update:semver-minor dependency-group: quarkus - dependency-name: io.quarkus.platform:quarkus-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: quarkus - dependency-name: io.quarkiverse.helm:quarkus-helm dependency-type: direct:production update-type: version-update:semver-patch dependency-group: quarkus - dependency-name: io.quarkus.platform:quarkus-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: quarkus ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8773ecd..9f812ab 100644 --- a/pom.xml +++ b/pom.xml @@ -14,14 +14,14 @@ UTF-8 quarkus-bom io.quarkus.platform - 3.14.3 + 3.15.1 1.11.0 3.26.0 true 3.5.1 2.43.0 apply - 1.2.4 + 1.2.5 From 28613aac5e3d516f76041cc8105229e5056d95b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:55:55 +0000 Subject: [PATCH 5/8] Bump org.apache.commons:commons-csv from 1.11.0 to 1.12.0 Bumps [org.apache.commons:commons-csv](https://github.com/apache/commons-csv) from 1.11.0 to 1.12.0. - [Changelog](https://github.com/apache/commons-csv/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-csv/compare/rel/commons-csv-1.11.0...rel/commons-csv-1.12.0) --- updated-dependencies: - dependency-name: org.apache.commons:commons-csv dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9f812ab..5ded7dd 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ quarkus-bom io.quarkus.platform 3.15.1 - 1.11.0 + 1.12.0 3.26.0 true 3.5.1 From d05a0ddfa672e94c619bf63290afcf572d290038 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 18 Oct 2024 16:14:07 +0200 Subject: [PATCH 6/8] Fix the fixversion format in the csv export test --- .../infra/replicate/jira/export/ExportProjectTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/hibernate/infra/replicate/jira/export/ExportProjectTest.java b/src/test/java/org/hibernate/infra/replicate/jira/export/ExportProjectTest.java index d7fd633..556946f 100644 --- a/src/test/java/org/hibernate/infra/replicate/jira/export/ExportProjectTest.java +++ b/src/test/java/org/hibernate/infra/replicate/jira/export/ExportProjectTest.java @@ -154,7 +154,7 @@ private List formatLabels(JiraIssue issue) { if (issue.fields.fixVersions != null) { for (JiraSimpleObject fixVersion : issue.fields.fixVersions) { - labels.add("Fix version: %s".formatted(fixVersion.name)); + labels.add("Fix version: %s".formatted(fixVersion.name).replace(' ', '_')); } } From 4e61f6bafdad91963b647a313f581932e5dd1d62 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 18 Oct 2024 21:20:28 +0200 Subject: [PATCH 7/8] Add an optional limit to init-sync --- .../jira/service/jira/HandlerProjectContext.java | 3 +++ .../infra/replicate/jira/service/jira/JiraService.java | 10 ++++++++-- .../jira/service/jira/handler/JiraEventHandler.java | 3 +++ .../service/reporting/LoggingFailureCollector.java | 4 ++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectContext.java b/src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectContext.java index e9d1bef..8e4020e 100644 --- a/src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectContext.java +++ b/src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectContext.java @@ -138,6 +138,9 @@ public void createNextPlaceholderBatch(Long upToKeyNumber) { JiraIssueBulkResponse response = destinationJiraClient.create(bulk); response.issues.stream().mapToLong(i -> JiraIssue.keyToLong(i.key)).max() .ifPresent(currentIssueKeyNumber::set); + Log.infof( + "Created more sync placeholders for %s; Current latest Jira key number is %s while required key is %s", + projectName, currentIssueKeyNumber.get(), upToKeyNumber); } while (currentIssueKeyNumber.get() < upToKeyNumber); } finally { lock.unlock(); diff --git a/src/main/java/org/hibernate/infra/replicate/jira/service/jira/JiraService.java b/src/main/java/org/hibernate/infra/replicate/jira/service/jira/JiraService.java index ae15f0c..11cd9d0 100644 --- a/src/main/java/org/hibernate/infra/replicate/jira/service/jira/JiraService.java +++ b/src/main/java/org/hibernate/infra/replicate/jira/service/jira/JiraService.java @@ -7,7 +7,9 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.BooleanSupplier; import org.hibernate.infra.replicate.jira.JiraConfig; import org.hibernate.infra.replicate.jira.service.jira.client.JiraRestClient; @@ -109,6 +111,10 @@ public void registerManagementRoutes(@Observes ManagementInterface mi) { // TODO: we can remove this one once we figure out why POST management does not // work correctly... String project = rc.pathParam("project"); + List maxToSyncList = rc.queryParam("maxToSync"); + AtomicInteger maxToSync = maxToSyncList.isEmpty() + ? null + : new AtomicInteger(Integer.parseInt(maxToSyncList.get(0)) + 1); HandlerProjectContext context = contextPerProject.get(project); @@ -117,14 +123,14 @@ public void registerManagementRoutes(@Observes ManagementInterface mi) { } AtomicLong largestSyncedJiraIssueKeyNumber = new AtomicLong(context.getLargestSyncedJiraIssueKeyNumber()); - + BooleanSupplier continueSyncing = maxToSync == null ? () -> true : () -> maxToSync.decrementAndGet() > 0; String identity = "Init Sync for project %s".formatted(project); scheduler.newJob(identity).setConcurrentExecution(Scheduled.ConcurrentExecution.SKIP) // every 10 seconds: .setCron("0/10 * * * * ?").setTask(executionContext -> { Optional issueToSync = context .getNextIssueToSync(largestSyncedJiraIssueKeyNumber.get()); - if (issueToSync.isEmpty()) { + if (issueToSync.isEmpty() || !continueSyncing.getAsBoolean()) { scheduler.unscheduleJob(identity); } else { triggerSyncEvent(issueToSync.get(), context); diff --git a/src/main/java/org/hibernate/infra/replicate/jira/service/jira/handler/JiraEventHandler.java b/src/main/java/org/hibernate/infra/replicate/jira/service/jira/handler/JiraEventHandler.java index fcbe713..f651ea9 100644 --- a/src/main/java/org/hibernate/infra/replicate/jira/service/jira/handler/JiraEventHandler.java +++ b/src/main/java/org/hibernate/infra/replicate/jira/service/jira/handler/JiraEventHandler.java @@ -16,6 +16,7 @@ import org.hibernate.infra.replicate.jira.service.reporting.FailureCollector; import org.hibernate.infra.replicate.jira.service.reporting.ReportingConfig; +import io.quarkus.logging.Log; import jakarta.ws.rs.core.UriBuilder; public abstract class JiraEventHandler implements Runnable { @@ -158,6 +159,8 @@ public final void run() { Thread.currentThread().interrupt(); } finally { failureCollector.close(); + Log.infof("Pending events in %s to process: %s", context.projectGroupName(), + context.pendingEventsInCurrentContext()); } } diff --git a/src/main/java/org/hibernate/infra/replicate/jira/service/reporting/LoggingFailureCollector.java b/src/main/java/org/hibernate/infra/replicate/jira/service/reporting/LoggingFailureCollector.java index 21ab8c2..028cd9d 100644 --- a/src/main/java/org/hibernate/infra/replicate/jira/service/reporting/LoggingFailureCollector.java +++ b/src/main/java/org/hibernate/infra/replicate/jira/service/reporting/LoggingFailureCollector.java @@ -16,7 +16,7 @@ public void warning(String details) { @Override public void warning(String details, Exception exception) { - Log.warn(details, exception); + Log.warnf(exception, details); } @Override @@ -26,7 +26,7 @@ public void critical(String details) { @Override public void critical(String details, Exception exception) { - Log.error(details, exception); + Log.errorf(exception, details); } @Override From 7ebcf5ed12afb92e3e7eb0aedf7441fb494391d6 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 18 Oct 2024 21:35:33 +0200 Subject: [PATCH 8/8] Comment out Sanne for now as cannot add him to the project - account marked as inactive ... --- src/main/resources/application.properties | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a65de24..a87eeb0 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -64,12 +64,12 @@ quarkus.scheduler.start-mode=forced %prod,test.jira.project-group."hibernate".users.mapping."557058\:71e31052-f0d7-46e3-a9d7-8b9acd6998d8"=guillaume.smet ## Gunnar #%prod,test.jira.project-group."hibernate".users.mapping."557058\:6a9959ae-3b15-4370-ad41-e78c978f4f7b"=gunnar.morling -# Sanne -# or JIRAUSER247447 -%prod,test.jira.project-group."hibernate".users.mapping."557058\:99e61e65-956b-4a21-b29c-06057642e9ea"=sgrinove@redhat.com -%prod,test.jira.project-group."hibernate".users.mapping."557058\:690dd548-c602-4a58-9c7e-0923346f4e97"=sgrinove@redhat.com -%prod,test.jira.project-group."hibernate".users.mapping."70121\:05895251-ccc4-42d9-acf3-7800fcf17a4c"=sgrinove@redhat.com -%prod,test.jira.project-group."hibernate".users.mapping."557058\:f781de72-2c68-4904-9be1-937e6dcca29f"=sgrinove@redhat.com +## Sanne +## or JIRAUSER247447 +#%prod,test.jira.project-group."hibernate".users.mapping."557058\:99e61e65-956b-4a21-b29c-06057642e9ea"=sgrinove@redhat.com +#%prod,test.jira.project-group."hibernate".users.mapping."557058\:690dd548-c602-4a58-9c7e-0923346f4e97"=sgrinove@redhat.com +#%prod,test.jira.project-group."hibernate".users.mapping."70121\:05895251-ccc4-42d9-acf3-7800fcf17a4c"=sgrinove@redhat.com +#%prod,test.jira.project-group."hibernate".users.mapping."557058\:f781de72-2c68-4904-9be1-937e6dcca29f"=sgrinove@redhat.com ## Emmanuel #%prod,test.jira.project-group."hibernate".users.mapping."557058\:7146ccce-8d92-4967-a2e1-f09ff06cc122"=rhn-engineering-ebernard #%prod,test.jira.project-group."hibernate".users.mapping."557058\:60723d35-67e0-400b-9749-abf4e657a6bd"=rhn-engineering-ebernard