From f8ab976e564c977a02e8db582416e6c892db2cd3 Mon Sep 17 00:00:00 2001 From: Sonu Kumar Date: Mon, 22 Feb 2021 21:12:05 +0530 Subject: [PATCH 1/8] get pending/schedule/processing message count --- .../config/RqueueListenerBaseConfig.java | 7 ++ .../rqueue/metrics/RqueueQueueMetrics.java | 82 +++++++++++++++++++ .../tests/integration/BootMetricsTest.java | 5 ++ .../sonus21/rqueue/test/tests/MetricTest.java | 33 ++++++-- 4 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 rqueue-core/src/main/java/com/github/sonus21/rqueue/metrics/RqueueQueueMetrics.java diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java index 9a9c8e6d..2bf0203d 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java @@ -28,6 +28,7 @@ import com.github.sonus21.rqueue.core.impl.RqueueMessageTemplateImpl; import com.github.sonus21.rqueue.dao.RqueueStringDao; import com.github.sonus21.rqueue.dao.impl.RqueueStringDaoImpl; +import com.github.sonus21.rqueue.metrics.RqueueQueueMetrics; import com.github.sonus21.rqueue.utils.RedisUtils; import com.github.sonus21.rqueue.web.view.DateTimeFunction; import com.github.sonus21.rqueue.web.view.DeadLetterQueuesFunction; @@ -186,4 +187,10 @@ public JtwigViewResolver rqueueViewResolver() { viewResolver.setSuffix(".html"); return viewResolver; } + + @Bean + public RqueueQueueMetrics rqueueQueueMetrics( + RqueueRedisTemplate stringRqueueRedisTemplate) { + return new RqueueQueueMetrics(stringRqueueRedisTemplate); + } } diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/metrics/RqueueQueueMetrics.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/metrics/RqueueQueueMetrics.java new file mode 100644 index 00000000..083662ec --- /dev/null +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/metrics/RqueueQueueMetrics.java @@ -0,0 +1,82 @@ +/* + * Copyright 2021 Sonu Kumar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + * + */ + +package com.github.sonus21.rqueue.metrics; + +import com.github.sonus21.rqueue.common.RqueueRedisTemplate; +import com.github.sonus21.rqueue.core.EndpointRegistry; +import com.github.sonus21.rqueue.exception.QueueDoesNotExist; +import com.github.sonus21.rqueue.listener.QueueDetail; + +/** + * This class reports queue message counter. + * + *

Count can be sent to some monitoring tool like Prometheus, influx db etc + */ +public class RqueueQueueMetrics { + + private final RqueueRedisTemplate redisTemplate; + + public RqueueQueueMetrics(RqueueRedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + /** + * Get number of messages waiting for consumption + * + * @param queue queue name + * @return -1 if queue is not registered otherwise message count + */ + public long getPendingMessageCount(String queue) { + try { + QueueDetail queueDetail = EndpointRegistry.get(queue); + return redisTemplate.getListSize(queueDetail.getQueueName()); + } catch (QueueDoesNotExist e) { + return -1; + } + } + + /** + * Get number of messages waiting in delayed queue, these messages would move to pending queue as + * soon as the scheduled time is reach. + * + * @param queue queue name + * @return -1 if queue is not registered otherwise message count + */ + public long getScheduledMessageCount(String queue) { + try { + QueueDetail queueDetail = EndpointRegistry.get(queue); + return redisTemplate.getZsetSize(queueDetail.getDelayedQueueName()); + } catch (QueueDoesNotExist e) { + return -1; + } + } + + /** + * Get number of messages those are currently being processed + * + * @param queue queue name + * @return -1 if queue is not registered otherwise message count + */ + public long getProcessingMessageCount(String queue) { + try { + QueueDetail queueDetail = EndpointRegistry.get(queue); + return redisTemplate.getZsetSize(queueDetail.getProcessingQueueName()); + } catch (QueueDoesNotExist e) { + return -1; + } + } +} diff --git a/rqueue-spring-boot-starter/src/test/java/com/github/sonus21/rqueue/spring/boot/tests/integration/BootMetricsTest.java b/rqueue-spring-boot-starter/src/test/java/com/github/sonus21/rqueue/spring/boot/tests/integration/BootMetricsTest.java index 99ccc101..d346669e 100644 --- a/rqueue-spring-boot-starter/src/test/java/com/github/sonus21/rqueue/spring/boot/tests/integration/BootMetricsTest.java +++ b/rqueue-spring-boot-starter/src/test/java/com/github/sonus21/rqueue/spring/boot/tests/integration/BootMetricsTest.java @@ -57,4 +57,9 @@ void metricStatus() throws TimedOutException { void countStatusTest() throws TimedOutException { this.verifyCountStatus(); } + + @Test + void messageCount() throws TimedOutException { + verifyQueueMessageCount(); + } } diff --git a/rqueue-spring-common-test/src/main/java/com/github/sonus21/rqueue/test/tests/MetricTest.java b/rqueue-spring-common-test/src/main/java/com/github/sonus21/rqueue/test/tests/MetricTest.java index 1e43eabe..22734c2d 100644 --- a/rqueue-spring-common-test/src/main/java/com/github/sonus21/rqueue/test/tests/MetricTest.java +++ b/rqueue-spring-common-test/src/main/java/com/github/sonus21/rqueue/test/tests/MetricTest.java @@ -19,18 +19,26 @@ import static com.github.sonus21.rqueue.utils.TimeoutUtils.waitFor; import static com.google.common.collect.Lists.newArrayList; +import com.github.sonus21.rqueue.core.EndpointRegistry; import com.github.sonus21.rqueue.exception.TimedOutException; +import com.github.sonus21.rqueue.listener.QueueDetail; +import com.github.sonus21.rqueue.metrics.RqueueQueueMetrics; import com.github.sonus21.rqueue.test.common.SpringTestBase; import com.github.sonus21.rqueue.test.dto.Email; import com.github.sonus21.rqueue.test.dto.Job; import com.github.sonus21.rqueue.test.dto.Notification; import com.github.sonus21.rqueue.utils.Constants; +import com.github.sonus21.rqueue.utils.TimeoutUtils; import io.micrometer.core.instrument.MeterRegistry; import java.time.Instant; import org.springframework.beans.factory.annotation.Autowired; public abstract class MetricTest extends SpringTestBase { - @Autowired protected MeterRegistry meterRegistry; + + @Autowired + protected MeterRegistry meterRegistry; + @Autowired + protected RqueueQueueMetrics rqueueQueueMetrics; protected void verifyDelayedQueueStatus() throws TimedOutException { long maxDelay = 0; @@ -141,12 +149,25 @@ protected void verifyCountStatus() throws TimedOutException { waitFor( () -> meterRegistry - .get("failure.count") - .tags("rqueue", "test") - .tags("queue", emailQueue) - .counter() - .count() + .get("failure.count") + .tags("rqueue", "test") + .tags("queue", emailQueue) + .counter() + .count() == 0, "stats collection"); } + + protected void verifyQueueMessageCount() throws TimedOutException { + QueueDetail queueDetail = EndpointRegistry.get(notificationQueue); + enqueue(queueDetail.getQueueName(), i -> Notification.newInstance(), 1000); + enqueueIn(queueDetail.getDelayedQueueName(), i -> Notification.newInstance(), i -> 30_000L, + 100); + TimeoutUtils.waitFor(() -> rqueueQueueMetrics.getProcessingMessageCount(notificationQueue) > 0, + "at least one message in processing"); + TimeoutUtils.waitFor(() -> rqueueQueueMetrics.getScheduledMessageCount(notificationQueue) > 0, + "at least one message in scheduled queue"); + TimeoutUtils.waitFor(() -> rqueueQueueMetrics.getPendingMessageCount(notificationQueue) > 0, + "at least one message in pending queue"); + } } From 235d95e3f3ab845d5ab52fd3cbfc4440f2056492 Mon Sep 17 00:00:00 2001 From: Sonu Kumar Date: Tue, 23 Feb 2021 08:03:08 +0530 Subject: [PATCH 2/8] Counter for priority based queue --- .../rqueue/annotation/RqueueListener.java | 9 ++-- .../sonus21/rqueue/core/EndpointRegistry.java | 19 +++++++ .../rqueue/listener/RqueueMessagePoller.java | 7 +-- .../rqueue/listener/StrictPriorityPoller.java | 1 + .../rqueue/metrics/RqueueQueueMetrics.java | 49 +++++++++++++++++++ .../application/BootMetricApplication.java | 47 ++++++++++++++++++ .../tests/integration/BootMetricsTest.java | 14 ++++-- .../sonus21/rqueue/test/tests/MetricTest.java | 32 +++++++++--- 8 files changed, 162 insertions(+), 16 deletions(-) create mode 100644 rqueue-spring-boot-starter/src/test/java/com/github/sonus21/rqueue/spring/boot/application/BootMetricApplication.java diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/annotation/RqueueListener.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/annotation/RqueueListener.java index 3914d8e6..cb01bf9a 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/annotation/RqueueListener.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/annotation/RqueueListener.java @@ -171,13 +171,16 @@ * weighted a round robin approach is used, and weight is followed. * * @return the priority for this listener. + * @see #priorityGroup() */ String priority() default ""; /** - * Priority group for this listener. More than one priority group can be configured in an - * application. Priority groups are useful when inside a group some queue(s) have higher priority - * then the queue(s). + * Priority group for this listener. + * + *

More than one priority group can be configured in an application. Priority groups are + * useful + * when inside a group some queue(s) have higher priority than the other queue(s). * * @return priority group name. */ diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/core/EndpointRegistry.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/core/EndpointRegistry.java index ca370692..a4682251 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/core/EndpointRegistry.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/core/EndpointRegistry.java @@ -19,6 +19,7 @@ import com.github.sonus21.rqueue.exception.OverrideException; import com.github.sonus21.rqueue.exception.QueueDoesNotExist; import com.github.sonus21.rqueue.listener.QueueDetail; +import com.github.sonus21.rqueue.utils.PriorityUtils; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -44,6 +45,7 @@ private EndpointRegistry() {} * @param queueName queue name * @return queue detail * @throws QueueDoesNotExist this error is thrown when queue is not registered. + * @see #get(String, String) */ public static QueueDetail get(String queueName) { QueueDetail queueDetail = queueNameToDetail.get(queueName); @@ -53,6 +55,23 @@ public static QueueDetail get(String queueName) { return queueDetail; } + /** + * Get QueueDetail for the given queue, with priority + * + * @param queueName queue name + * @param priority priority of this queue like critical, high + * @return queue detail + * @throws QueueDoesNotExist this error is thrown when queue is not registered. + */ + public static QueueDetail get(String queueName, String priority) { + QueueDetail queueDetail = + queueNameToDetail.get(PriorityUtils.getQueueNameForPriority(queueName, priority)); + if (queueDetail == null) { + throw new QueueDoesNotExist(queueName); + } + return queueDetail; + } + public static void register(QueueDetail queueDetail) { synchronized (lock) { if (queueNameToDetail.containsKey(queueDetail.getName())) { diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/listener/RqueueMessagePoller.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/listener/RqueueMessagePoller.java index de043a34..0bf5fb9a 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/listener/RqueueMessagePoller.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/listener/RqueueMessagePoller.java @@ -69,8 +69,7 @@ private void execute(QueueThread queueThread, QueueDetail queueDetail, RqueueMes postProcessingHandler, message, queueDetail, - queueThread.getSemaphore() - )); + queueThread.getSemaphore())); } boolean shouldExit() { @@ -96,7 +95,9 @@ void poll(int index, String queue, QueueDetail queueDetail, QueueThread queueThr } if (!acquired) { deactivate(index, queue, DeactivateType.SEMAPHORE_UNAVAILABLE); - } else if (isQueueActive(queue)) { + return; + } + if (isQueueActive(queue)) { try { RqueueMessage message = getMessage(queueDetail); log(Level.DEBUG, "Queue: {} Fetched Msg {}", null, queue, message); diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/listener/StrictPriorityPoller.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/listener/StrictPriorityPoller.java index 2c70180d..300cb369 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/listener/StrictPriorityPoller.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/listener/StrictPriorityPoller.java @@ -59,6 +59,7 @@ class StrictPriorityPoller extends RqueueMessagePoller { private String getQueueToPoll() { long now = System.currentTimeMillis(); + // starvation for (String queue : queues) { if (isQueueActive(queue)) { if (now - lastFetchedTime.get(queue) > Constants.MILLIS_IN_A_MINUTE) { diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/metrics/RqueueQueueMetrics.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/metrics/RqueueQueueMetrics.java index 083662ec..8194b2a9 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/metrics/RqueueQueueMetrics.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/metrics/RqueueQueueMetrics.java @@ -79,4 +79,53 @@ public long getProcessingMessageCount(String queue) { return -1; } } + + /** + * Get number of messages waiting for consumption + * + * @param queue queue name + * @param priority priority of this queue + * @return -1 if queue is not registered otherwise message count + */ + public long getPendingMessageCount(String queue, String priority) { + try { + QueueDetail queueDetail = EndpointRegistry.get(queue, priority); + return redisTemplate.getListSize(queueDetail.getQueueName()); + } catch (QueueDoesNotExist e) { + return -1; + } + } + + /** + * Get number of messages waiting in delayed queue, these messages would move to pending queue as + * soon as the scheduled time is reach. + * + * @param queue queue name + * @param priority priority of this queue + * @return -1 if queue is not registered otherwise message count + */ + public long getScheduledMessageCount(String queue, String priority) { + try { + QueueDetail queueDetail = EndpointRegistry.get(queue, priority); + return redisTemplate.getZsetSize(queueDetail.getDelayedQueueName()); + } catch (QueueDoesNotExist e) { + return -1; + } + } + + /** + * Get number of messages those are currently being processed + * + * @param queue queue name + * @param priority priority of this queue + * @return -1 if queue is not registered otherwise message count + */ + public long getProcessingMessageCount(String queue, String priority) { + try { + QueueDetail queueDetail = EndpointRegistry.get(queue, priority); + return redisTemplate.getZsetSize(queueDetail.getProcessingQueueName()); + } catch (QueueDoesNotExist e) { + return -1; + } + } } diff --git a/rqueue-spring-boot-starter/src/test/java/com/github/sonus21/rqueue/spring/boot/application/BootMetricApplication.java b/rqueue-spring-boot-starter/src/test/java/com/github/sonus21/rqueue/spring/boot/application/BootMetricApplication.java new file mode 100644 index 00000000..0079fea7 --- /dev/null +++ b/rqueue-spring-boot-starter/src/test/java/com/github/sonus21/rqueue/spring/boot/application/BootMetricApplication.java @@ -0,0 +1,47 @@ +/* + * Copyright 2021 Sonu Kumar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + * + */ + +package com.github.sonus21.rqueue.spring.boot.application; + +import com.github.sonus21.rqueue.config.SimpleRqueueListenerContainerFactory; +import com.github.sonus21.rqueue.models.enums.PriorityMode; +import com.github.sonus21.rqueue.test.application.BaseApplication; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.PropertySource; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@PropertySource("classpath:application.properties") +@SpringBootApplication(scanBasePackages = {"com.github.sonus21.rqueue.test"}) +@EnableRedisRepositories +@EnableJpaRepositories(basePackages = {"com.github.sonus21.rqueue.test.repository"}) +@EnableTransactionManagement +public class BootMetricApplication extends BaseApplication { + + public static void main(String[] args) { + SpringApplication.run(BootMetricApplication.class, args); + } + + @Bean + public SimpleRqueueListenerContainerFactory simpleRqueueListenerContainerFactory() { + SimpleRqueueListenerContainerFactory factory = new SimpleRqueueListenerContainerFactory(); + factory.setPriorityMode(PriorityMode.WEIGHTED); + return factory; + } +} diff --git a/rqueue-spring-boot-starter/src/test/java/com/github/sonus21/rqueue/spring/boot/tests/integration/BootMetricsTest.java b/rqueue-spring-boot-starter/src/test/java/com/github/sonus21/rqueue/spring/boot/tests/integration/BootMetricsTest.java index d346669e..caedc600 100644 --- a/rqueue-spring-boot-starter/src/test/java/com/github/sonus21/rqueue/spring/boot/tests/integration/BootMetricsTest.java +++ b/rqueue-spring-boot-starter/src/test/java/com/github/sonus21/rqueue/spring/boot/tests/integration/BootMetricsTest.java @@ -17,7 +17,7 @@ package com.github.sonus21.rqueue.spring.boot.tests.integration; import com.github.sonus21.rqueue.exception.TimedOutException; -import com.github.sonus21.rqueue.spring.boot.application.Application; +import com.github.sonus21.rqueue.spring.boot.application.BootMetricApplication; import com.github.sonus21.rqueue.spring.boot.tests.SpringBootIntegrationTest; import com.github.sonus21.rqueue.test.tests.MetricTest; import lombok.extern.slf4j.Slf4j; @@ -28,7 +28,7 @@ import org.springframework.test.context.TestPropertySource; @SpringBootTest -@ContextConfiguration(classes = Application.class) +@ContextConfiguration(classes = BootMetricApplication.class) @Slf4j @TestPropertySource( properties = { @@ -38,6 +38,7 @@ "mysql.db.name=test4", "rqueue.metrics.count.failure=true", "rqueue.metrics.count.execution=true", + "sms.queue.active=true" }) @SpringBootIntegrationTest class BootMetricsTest extends MetricTest { @@ -59,7 +60,12 @@ void countStatusTest() throws TimedOutException { } @Test - void messageCount() throws TimedOutException { - verifyQueueMessageCount(); + void simpleQueueMessageCount() throws TimedOutException { + verifyNotificationQueueMessageCount(); + } + + @Test + void priorityQueueMessageCount() throws TimedOutException { + verifySmsQueueMessageCount(); } } diff --git a/rqueue-spring-common-test/src/main/java/com/github/sonus21/rqueue/test/tests/MetricTest.java b/rqueue-spring-common-test/src/main/java/com/github/sonus21/rqueue/test/tests/MetricTest.java index 22734c2d..bc31c677 100644 --- a/rqueue-spring-common-test/src/main/java/com/github/sonus21/rqueue/test/tests/MetricTest.java +++ b/rqueue-spring-common-test/src/main/java/com/github/sonus21/rqueue/test/tests/MetricTest.java @@ -27,6 +27,7 @@ import com.github.sonus21.rqueue.test.dto.Email; import com.github.sonus21.rqueue.test.dto.Job; import com.github.sonus21.rqueue.test.dto.Notification; +import com.github.sonus21.rqueue.test.dto.Sms; import com.github.sonus21.rqueue.utils.Constants; import com.github.sonus21.rqueue.utils.TimeoutUtils; import io.micrometer.core.instrument.MeterRegistry; @@ -158,16 +159,35 @@ protected void verifyCountStatus() throws TimedOutException { "stats collection"); } - protected void verifyQueueMessageCount() throws TimedOutException { + protected void verifyNotificationQueueMessageCount() throws TimedOutException { QueueDetail queueDetail = EndpointRegistry.get(notificationQueue); enqueue(queueDetail.getQueueName(), i -> Notification.newInstance(), 1000); - enqueueIn(queueDetail.getDelayedQueueName(), i -> Notification.newInstance(), i -> 30_000L, - 100); - TimeoutUtils.waitFor(() -> rqueueQueueMetrics.getProcessingMessageCount(notificationQueue) > 0, + enqueueIn( + queueDetail.getDelayedQueueName(), i -> Notification.newInstance(), i -> 30_000L, 100); + TimeoutUtils.waitFor( + () -> rqueueQueueMetrics.getProcessingMessageCount(notificationQueue) > 0, "at least one message in processing"); - TimeoutUtils.waitFor(() -> rqueueQueueMetrics.getScheduledMessageCount(notificationQueue) > 0, + TimeoutUtils.waitFor( + () -> rqueueQueueMetrics.getScheduledMessageCount(notificationQueue) > 0, "at least one message in scheduled queue"); - TimeoutUtils.waitFor(() -> rqueueQueueMetrics.getPendingMessageCount(notificationQueue) > 0, + TimeoutUtils.waitFor( + () -> rqueueQueueMetrics.getPendingMessageCount(notificationQueue) > 0, + "at least one message in pending queue"); + } + + protected void verifySmsQueueMessageCount() throws TimedOutException { + String priority = "critical"; + QueueDetail queueDetail = EndpointRegistry.get(smsQueue, priority); + enqueue(queueDetail.getQueueName(), i -> Sms.newInstance(), 1000); + enqueueIn(queueDetail.getDelayedQueueName(), i -> Sms.newInstance(), i -> 30_000L, 100); + TimeoutUtils.waitFor( + () -> rqueueQueueMetrics.getProcessingMessageCount(smsQueue, priority) > 0, + "at least one message in processing"); + TimeoutUtils.waitFor( + () -> rqueueQueueMetrics.getScheduledMessageCount(smsQueue, priority) > 0, + "at least one message in scheduled queue"); + TimeoutUtils.waitFor( + () -> rqueueQueueMetrics.getPendingMessageCount(smsQueue, priority) > 0, "at least one message in pending queue"); } } From e41bbfabbfa046043c561e6f7bd25836ff4502d5 Mon Sep 17 00:00:00 2001 From: Sonu Kumar Date: Wed, 24 Feb 2021 21:30:52 +0530 Subject: [PATCH 3/8] Pebble template #74 --- build.gradle | 13 ++- rqueue-core/build.gradle | 3 +- .../config/RqueueListenerBaseConfig.java | 24 ++---- .../pebble}/DateTimeFunction.java | 23 +++--- .../pebble}/DeadLetterQueuesFunction.java | 26 +++--- .../utils/pebble/RqueuePebbleExtension.java | 81 +++++++++++++++++++ .../web/controller/RqueueViewController.java | 7 +- .../rqueue/web/view/DateTimeFunctionTest.java | 14 ++-- .../integration/RqueueViewControllerTest.java | 34 ++++---- 9 files changed, 156 insertions(+), 69 deletions(-) rename rqueue-core/src/main/java/com/github/sonus21/rqueue/{web/view => utils/pebble}/DateTimeFunction.java (55%) rename rqueue-core/src/main/java/com/github/sonus21/rqueue/{web/view => utils/pebble}/DeadLetterQueuesFunction.java (66%) create mode 100644 rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/RqueuePebbleExtension.java diff --git a/build.gradle b/build.gradle index 49aa4c91..d2eb9556 100644 --- a/build.gradle +++ b/build.gradle @@ -53,7 +53,7 @@ ext { // server javaxServletVersion = '4.0.1' - twigVersion = '5.87.0.RELEASE' + pebbleVersion = '3.1.5' // database lettuceVersion = '5.2.0.RELEASE' @@ -63,6 +63,8 @@ ext { // other dependencies javaxValidationApiVersion = '2.0.1.Final' + + guavaVersion = '30.1-jre' } @@ -77,8 +79,15 @@ subprojects { // https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis compile group: 'org.springframework.data', name: 'spring-data-redis', version: "${springDataVersion}" + // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 + compile group: 'org.apache.commons', name: 'commons-lang3', version: "${lang3Version}" + + // https://mvnrepository.com/artifact/com.google.guava/guava + compile group: 'com.google.guava', name: 'guava', version: "${guavaVersion}" + compileOnly "org.projectlombok:lombok:${lombokVersion}" annotationProcessor "org.projectlombok:lombok:${lombokVersion}" + testCompile "org.projectlombok:lombok:${lombokVersion}" testAnnotationProcessor "org.projectlombok:lombok:${lombokVersion}" @@ -93,8 +102,6 @@ subprojects { testCompile group: 'org.mockito', name: 'mockito-junit-jupiter', version: "${mockitoVersion}" // https://mvnrepository.com/artifact/org.hamcrest/hamcrest testCompile group: 'org.hamcrest', name: 'hamcrest', version: "${hamcrestVersion}" - // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 - testCompile group: 'org.apache.commons', name: 'commons-lang3', version: "${lang3Version}" testCompile("org.springframework.boot:spring-boot-test:${springBootVersion}") testCompile group: 'org.junit-pioneer', name: 'junit-pioneer', version: '0.9.0' diff --git a/rqueue-core/build.gradle b/rqueue-core/build.gradle index 3302ccee..cd791b12 100644 --- a/rqueue-core/build.gradle +++ b/rqueue-core/build.gradle @@ -15,8 +15,7 @@ dependencies { compile group: 'javax.servlet', name: 'javax.servlet-api', version: "${javaxServletVersion}" // https://mvnrepository.com/artifact/org.springframework/spring-webmvc compile group: 'org.springframework', name: 'spring-webmvc', version: "${springVersion}" - // https://mvnrepository.com/artifact/org.jtwig/jtwig-spring - compile group: 'org.jtwig', name: 'jtwig-spring', version: "${twigVersion}" + compile "io.pebbletemplates:pebble-spring5:${pebbleVersion}" compile group: 'io.seruco.encoding', name: 'base62', version: "0.1.3" // https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 compile group: 'org.apache.commons', name: 'commons-collections4', version: '4.4' diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java index 2bf0203d..b3810fe2 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java @@ -30,12 +30,9 @@ import com.github.sonus21.rqueue.dao.impl.RqueueStringDaoImpl; import com.github.sonus21.rqueue.metrics.RqueueQueueMetrics; import com.github.sonus21.rqueue.utils.RedisUtils; -import com.github.sonus21.rqueue.web.view.DateTimeFunction; -import com.github.sonus21.rqueue.web.view.DeadLetterQueuesFunction; -import org.jtwig.environment.EnvironmentConfiguration; -import org.jtwig.environment.EnvironmentConfigurationBuilder; -import org.jtwig.spring.JtwigViewResolver; -import org.jtwig.web.servlet.JtwigRenderer; +import com.github.sonus21.rqueue.utils.pebble.RqueuePebbleExtension; +import com.mitchellbosecke.pebble.PebbleEngine; +import com.mitchellbosecke.pebble.spring.servlet.PebbleViewResolver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -172,17 +169,10 @@ public RqueueLockManager rqueueLockManager(RqueueStringDao rqueueStringDao) { } @Bean - public JtwigViewResolver rqueueViewResolver() { - EnvironmentConfiguration configuration = - EnvironmentConfigurationBuilder.configuration() - .functions() - .add(new DateTimeFunction()) - .add(new DeadLetterQueuesFunction()) - .and() - .build(); - JtwigRenderer renderer = new JtwigRenderer(configuration); - JtwigViewResolver viewResolver = new JtwigViewResolver(); - viewResolver.setRenderer(renderer); + public PebbleViewResolver rqueueViewResolver() { + PebbleEngine pebbleEngine = + new PebbleEngine.Builder().extension(new RqueuePebbleExtension()).build(); + PebbleViewResolver viewResolver = new PebbleViewResolver(pebbleEngine); viewResolver.setPrefix("classpath:/templates/rqueue/"); viewResolver.setSuffix(".html"); return viewResolver; diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/web/view/DateTimeFunction.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DateTimeFunction.java similarity index 55% rename from rqueue-core/src/main/java/com/github/sonus21/rqueue/web/view/DateTimeFunction.java rename to rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DateTimeFunction.java index fb06e7c6..be85cf76 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/web/view/DateTimeFunction.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DateTimeFunction.java @@ -14,22 +14,27 @@ * */ -package com.github.sonus21.rqueue.web.view; +package com.github.sonus21.rqueue.utils.pebble; import com.github.sonus21.rqueue.utils.DateTimeUtils; -import org.jtwig.functions.FunctionRequest; -import org.jtwig.functions.SimpleJtwigFunction; +import com.mitchellbosecke.pebble.extension.Function; +import com.mitchellbosecke.pebble.template.EvaluationContext; +import com.mitchellbosecke.pebble.template.PebbleTemplate; +import java.util.Collections; +import java.util.List; +import java.util.Map; -public class DateTimeFunction extends SimpleJtwigFunction { +public class DateTimeFunction implements Function { @Override - public String name() { - return "time"; + public Object execute( + Map args, PebbleTemplate self, EvaluationContext context, int lineNumber) { + Long milli = (Long) args.get("milli"); + return DateTimeUtils.formatMilliToString(milli); } @Override - public Object execute(FunctionRequest request) { - Long milli = (Long) request.getArguments().get(0); - return DateTimeUtils.formatMilliToString(milli); + public List getArgumentNames() { + return Collections.singletonList("milli"); } } diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/web/view/DeadLetterQueuesFunction.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DeadLetterQueuesFunction.java similarity index 66% rename from rqueue-core/src/main/java/com/github/sonus21/rqueue/web/view/DeadLetterQueuesFunction.java rename to rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DeadLetterQueuesFunction.java index 9288a36b..62cdb20b 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/web/view/DeadLetterQueuesFunction.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DeadLetterQueuesFunction.java @@ -14,25 +14,26 @@ * */ -package com.github.sonus21.rqueue.web.view; +package com.github.sonus21.rqueue.utils.pebble; import com.github.sonus21.rqueue.models.db.DeadLetterQueue; +import com.mitchellbosecke.pebble.extension.Function; +import com.mitchellbosecke.pebble.template.EvaluationContext; +import com.mitchellbosecke.pebble.template.PebbleTemplate; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; -import org.jtwig.functions.FunctionRequest; -import org.jtwig.functions.SimpleJtwigFunction; import org.springframework.util.CollectionUtils; @SuppressWarnings("unchecked") -public class DeadLetterQueuesFunction extends SimpleJtwigFunction { - @Override - public String name() { - return "dlq"; - } +public class DeadLetterQueuesFunction implements Function { @Override - public Object execute(FunctionRequest request) { - List deadLetterQueues = (List) request.getArguments().get(0); + public Object execute( + Map args, PebbleTemplate self, EvaluationContext context, int lineNumber) { + List deadLetterQueues = (List) args.get("queues"); + if (CollectionUtils.isEmpty(deadLetterQueues)) { return ""; } @@ -40,4 +41,9 @@ public Object execute(FunctionRequest request) { deadLetterQueues.stream().map(DeadLetterQueue::getName).collect(Collectors.toList()); return String.join(",", queues); } + + @Override + public List getArgumentNames() { + return Collections.singletonList("queues"); + } } diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/RqueuePebbleExtension.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/RqueuePebbleExtension.java new file mode 100644 index 00000000..9ce4532f --- /dev/null +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/RqueuePebbleExtension.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021 Sonu Kumar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + * + */ + +package com.github.sonus21.rqueue.utils.pebble; + +import com.mitchellbosecke.pebble.attributes.AttributeResolver; +import com.mitchellbosecke.pebble.extension.Extension; +import com.mitchellbosecke.pebble.extension.Filter; +import com.mitchellbosecke.pebble.extension.Function; +import com.mitchellbosecke.pebble.extension.NodeVisitorFactory; +import com.mitchellbosecke.pebble.extension.Test; +import com.mitchellbosecke.pebble.operator.BinaryOperator; +import com.mitchellbosecke.pebble.operator.UnaryOperator; +import com.mitchellbosecke.pebble.tokenParser.TokenParser; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class RqueuePebbleExtension implements Extension { + + @Override + public Map getFilters() { + return null; + } + + @Override + public Map getTests() { + return null; + } + + @Override + public Map getFunctions() { + Map map = new HashMap<>(); + map.put("dlq", new DeadLetterQueuesFunction()); + map.put("time", new DateTimeFunction()); + return map; + } + + @Override + public List getTokenParsers() { + return null; + } + + @Override + public List getBinaryOperators() { + return null; + } + + @Override + public List getUnaryOperators() { + return null; + } + + @Override + public Map getGlobalVariables() { + return null; + } + + @Override + public List getNodeVisitors() { + return null; + } + + @Override + public List getAttributeResolver() { + return null; + } +} diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/web/controller/RqueueViewController.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/web/controller/RqueueViewController.java index f82a2ac5..3164cca1 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/web/controller/RqueueViewController.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/web/controller/RqueueViewController.java @@ -28,6 +28,7 @@ import com.github.sonus21.rqueue.web.service.RqueueQDetailService; import com.github.sonus21.rqueue.web.service.RqueueSystemManagerService; import com.github.sonus21.rqueue.web.service.RqueueUtilityService; +import com.mitchellbosecke.pebble.spring.servlet.PebbleViewResolver; import io.seruco.encoding.base62.Base62; import java.nio.ByteBuffer; import java.time.OffsetDateTime; @@ -40,7 +41,6 @@ import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.jtwig.spring.JtwigViewResolver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.util.Pair; @@ -54,7 +54,8 @@ @Controller @RequestMapping("rqueue") public class RqueueViewController { - private final JtwigViewResolver rqueueViewResolver; + + private final PebbleViewResolver rqueueViewResolver; private final RqueueConfig rqueueConfig; private final RqueueWebConfig rqueueWebConfig; private final RqueueQDetailService rqueueQDetailService; @@ -64,7 +65,7 @@ public class RqueueViewController { @Autowired public RqueueViewController( - @Qualifier("rqueueViewResolver") JtwigViewResolver rqueueViewResolver, + @Qualifier("rqueueViewResolver") PebbleViewResolver rqueueViewResolver, RqueueConfig rqueueConfig, RqueueWebConfig rqueueWebConfig, RqueueQDetailService rqueueQDetailService, diff --git a/rqueue-core/src/test/java/com/github/sonus21/rqueue/web/view/DateTimeFunctionTest.java b/rqueue-core/src/test/java/com/github/sonus21/rqueue/web/view/DateTimeFunctionTest.java index 44bb8221..f28e4fcf 100644 --- a/rqueue-core/src/test/java/com/github/sonus21/rqueue/web/view/DateTimeFunctionTest.java +++ b/rqueue-core/src/test/java/com/github/sonus21/rqueue/web/view/DateTimeFunctionTest.java @@ -17,13 +17,11 @@ package com.github.sonus21.rqueue.web.view; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; import com.github.sonus21.TestBase; import com.github.sonus21.rqueue.CoreUnitTest; +import com.github.sonus21.rqueue.utils.pebble.DateTimeFunction; import java.util.Collections; -import org.jtwig.functions.FunctionRequest; import org.junit.jupiter.api.Test; @CoreUnitTest @@ -31,14 +29,14 @@ class DateTimeFunctionTest extends TestBase { private final DateTimeFunction function = new DateTimeFunction(); @Test - void name() { - assertEquals("time", function.name()); + void getArguments() { + assertEquals(Collections.singletonList("milli"), function.getArgumentNames()); } @Test void execute() { - FunctionRequest request = mock(FunctionRequest.class); - doReturn(Collections.singletonList(1588335692988L)).when(request).getArguments(); - assertEquals("01 May 2020 12:21", function.execute(request)); + assertEquals( + "01 May 2020 12:21", + function.execute(Collections.singletonMap("milli", 1588335692988L), null, null, -1)); } } diff --git a/rqueue-spring/src/test/java/com/github/sonus21/rqueue/spring/tests/integration/RqueueViewControllerTest.java b/rqueue-spring/src/test/java/com/github/sonus21/rqueue/spring/tests/integration/RqueueViewControllerTest.java index e11e8e8a..d5f2caa2 100644 --- a/rqueue-spring/src/test/java/com/github/sonus21/rqueue/spring/tests/integration/RqueueViewControllerTest.java +++ b/rqueue-spring/src/test/java/com/github/sonus21/rqueue/spring/tests/integration/RqueueViewControllerTest.java @@ -26,9 +26,9 @@ import com.github.sonus21.rqueue.spring.app.SpringApp; import com.github.sonus21.rqueue.spring.tests.SpringIntegrationTest; import com.github.sonus21.rqueue.test.common.SpringWebTestBase; +import com.mitchellbosecke.pebble.spring.servlet.PebbleView; import java.util.Arrays; import lombok.extern.slf4j.Slf4j; -import org.jtwig.spring.JtwigView; import org.junit.jupiter.api.Test; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; @@ -64,8 +64,8 @@ private void verifyBasicData(ModelMap model, NavTab navTab) { void home() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); - JtwigView jtwigView = (JtwigView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/index.html", jtwigView.getUrl()); + PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); + assertEquals("classpath:/templates/rqueue/index.html", pebbleView.getUrl()); verifyBasicData(model, null); assertEquals( Arrays.asList(AggregationType.DAILY, AggregationType.WEEKLY, AggregationType.MONTHLY), @@ -83,8 +83,8 @@ void home() throws Exception { void queues() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/queues")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); - JtwigView jtwigView = (JtwigView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/queues.html", jtwigView.getUrl()); + PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); + assertEquals("classpath:/templates/rqueue/queues.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.QUEUES); assertEquals("Queues", model.get("title")); assertNotNull(model.get("queues")); @@ -95,8 +95,8 @@ void queues() throws Exception { void queueDetail() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/queues/" + jobQueue)).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); - JtwigView jtwigView = (JtwigView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/queue_detail.html", jtwigView.getUrl()); + PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); + assertEquals("classpath:/templates/rqueue/queue_detail.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.QUEUES); assertEquals("Queue: " + jobQueue, model.get("title")); assertEquals(jobQueue, model.get("queueName")); @@ -120,8 +120,8 @@ void queueDetail() throws Exception { void running() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/running")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); - JtwigView jtwigView = (JtwigView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/running.html", jtwigView.getUrl()); + PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); + assertEquals("classpath:/templates/rqueue/running.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.RUNNING); assertEquals("Running Tasks", model.get("title")); assertNotNull(model.get("tasks")); @@ -132,8 +132,8 @@ void running() throws Exception { void scheduled() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/scheduled")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); - JtwigView jtwigView = (JtwigView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/running.html", jtwigView.getUrl()); + PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); + assertEquals("classpath:/templates/rqueue/running.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.SCHEDULED); assertEquals("Scheduled Tasks", model.get("title")); assertNotNull(model.get("tasks")); @@ -144,8 +144,8 @@ void scheduled() throws Exception { void dead() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/dead")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); - JtwigView jtwigView = (JtwigView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/running.html", jtwigView.getUrl()); + PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); + assertEquals("classpath:/templates/rqueue/running.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.DEAD); assertEquals("Tasks moved to dead letter queue", model.get("title")); assertNotNull(model.get("tasks")); @@ -156,8 +156,8 @@ void dead() throws Exception { void pending() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/pending")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); - JtwigView jtwigView = (JtwigView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/running.html", jtwigView.getUrl()); + PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); + assertEquals("classpath:/templates/rqueue/running.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.PENDING); assertEquals("Tasks waiting for execution", model.get("title")); assertNotNull(model.get("tasks")); @@ -168,8 +168,8 @@ void pending() throws Exception { void utility() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/utility")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); - JtwigView jtwigView = (JtwigView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/utility.html", jtwigView.getUrl()); + PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); + assertEquals("classpath:/templates/rqueue/utility.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.UTILITY); assertEquals("Utility", model.get("title")); assertNotNull(model.get("supportedDataType")); From adce28a50845811823495b3eda6577b1f15b5593 Mon Sep 17 00:00:00 2001 From: Sonu Kumar Date: Wed, 24 Feb 2021 22:28:02 +0530 Subject: [PATCH 4/8] wip --- .../config/RqueueListenerBaseConfig.java | 16 ++- .../rqueue/utils/pebble/ResourceLoader.java | 101 ++++++++++++++++++ .../sonus21/rqueue/example/Controller.java | 29 ----- 3 files changed, 112 insertions(+), 34 deletions(-) create mode 100644 rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/ResourceLoader.java diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java index b3810fe2..039302df 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java @@ -30,8 +30,10 @@ import com.github.sonus21.rqueue.dao.impl.RqueueStringDaoImpl; import com.github.sonus21.rqueue.metrics.RqueueQueueMetrics; import com.github.sonus21.rqueue.utils.RedisUtils; +import com.github.sonus21.rqueue.utils.pebble.ResourceLoader; import com.github.sonus21.rqueue.utils.pebble.RqueuePebbleExtension; import com.mitchellbosecke.pebble.PebbleEngine; +import com.mitchellbosecke.pebble.loader.Loader; import com.mitchellbosecke.pebble.spring.servlet.PebbleViewResolver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -170,12 +172,16 @@ public RqueueLockManager rqueueLockManager(RqueueStringDao rqueueStringDao) { @Bean public PebbleViewResolver rqueueViewResolver() { + Loader resourceLoader = new ResourceLoader(); PebbleEngine pebbleEngine = - new PebbleEngine.Builder().extension(new RqueuePebbleExtension()).build(); - PebbleViewResolver viewResolver = new PebbleViewResolver(pebbleEngine); - viewResolver.setPrefix("classpath:/templates/rqueue/"); - viewResolver.setSuffix(".html"); - return viewResolver; + new PebbleEngine.Builder() + .extension(new RqueuePebbleExtension()) + .loader(resourceLoader) + .build(); + PebbleViewResolver resolver = new PebbleViewResolver(pebbleEngine); + resolver.setPrefix("classpath:/templates/rqueue/"); + resolver.setSuffix(".html"); + return resolver; } @Bean diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/ResourceLoader.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/ResourceLoader.java new file mode 100644 index 00000000..4c218425 --- /dev/null +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/ResourceLoader.java @@ -0,0 +1,101 @@ +/* + * Copyright 2021 Sonu Kumar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + * + */ + +package com.github.sonus21.rqueue.utils.pebble; + +import com.mitchellbosecke.pebble.error.LoaderException; +import com.mitchellbosecke.pebble.loader.Loader; +import com.mitchellbosecke.pebble.utils.PathUtils; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.ClassPathResource; + +@Slf4j +public class ResourceLoader implements Loader { + + private String prefix; + private String suffix; + private String charset = "UTF-8"; + + @Override + public Reader getReader(String templateName) { + String location = this.getLocation(templateName); + log.debug("Looking for template in {}.", location); + ClassPathResource resource = new ClassPathResource(location); + // perform the lookup + try { + InputStream is = resource.getInputStream(); + try { + return new BufferedReader(new InputStreamReader(is, this.charset)); + } catch (UnsupportedEncodingException e) { + } + } catch (IOException e) { + throw new LoaderException(null, "Could not find template \"" + location + "\""); + } + return null; + } + + private String getLocation(String templateName) { + return this.getPrefix() + templateName + this.getSuffix(); + } + + public String getSuffix() { + return this.suffix; + } + + @Override + public void setSuffix(String suffix) { + this.suffix = suffix; + } + + public String getPrefix() { + return this.prefix; + } + + @Override + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public String getCharset() { + return this.charset; + } + + @Override + public void setCharset(String charset) { + this.charset = charset; + } + + @Override + public String resolveRelativePath(String relativePath, String anchorPath) { + return PathUtils.resolveRelativePath(relativePath, anchorPath, '/'); + } + + @Override + public String createCacheKey(String templateName) { + return templateName; + } + + @Override + public boolean resourceExists(String templateName) { + return new ClassPathResource(getLocation(templateName)).exists(); + } +} diff --git a/rqueue-spring-boot-example/src/main/java/com/github/sonus21/rqueue/example/Controller.java b/rqueue-spring-boot-example/src/main/java/com/github/sonus21/rqueue/example/Controller.java index d75d8ec3..be139d90 100644 --- a/rqueue-spring-boot-example/src/main/java/com/github/sonus21/rqueue/example/Controller.java +++ b/rqueue-spring-boot-example/src/main/java/com/github/sonus21/rqueue/example/Controller.java @@ -17,24 +17,14 @@ package com.github.sonus21.rqueue.example; import com.github.sonus21.rqueue.core.RqueueMessageSender; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; import java.util.UUID; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthAggregator; -import org.springframework.boot.actuate.health.HealthEndpoint; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.HealthIndicatorRegistry; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import reactor.core.publisher.Mono; @RestController @AllArgsConstructor(onConstructor = @__(@Autowired)) @@ -42,27 +32,8 @@ public class Controller { private final RqueueMessageSender rqueueMessageSender; - private final HealthEndpoint healthEndpoint; - private final HealthAggregator healthAggregator; - private final HealthIndicatorRegistry healthIndicatorRegistry; - private final ReactiveHealthIndicator reactiveHealthIndicator; private final RedisTemplate redisTemplate; - @GetMapping("health") - public Health health() { - Map health = new HashMap<>(); - for (Entry entry : healthIndicatorRegistry.getAll().entrySet()) { - health.put(entry.getKey(), entry.getValue().health()); - } - - return healthAggregator.aggregate(health); - } - - @GetMapping("rhealth") - public Mono rhealth() { - return reactiveHealthIndicator.health(); - } - @GetMapping(value = "/push") public String push( String q, From 16a330352192b8d8eccae9f7c9a56908b4824d1b Mon Sep 17 00:00:00 2001 From: Sonu Kumar Date: Wed, 24 Feb 2021 23:08:04 +0530 Subject: [PATCH 5/8] pebble template change --- .../config/RqueueListenerBaseConfig.java | 9 ++- .../rqueue/utils/pebble/DateTimeFunction.java | 1 + .../pebble/DeadLetterQueuesFunction.java | 1 + .../rqueue/utils/pebble/DefaultFunction.java | 45 +++++++++++++++ .../utils/pebble/RqueuePebbleExtension.java | 57 ++----------------- .../resources/templates/rqueue/index.html | 6 +- .../templates/rqueue/queue_detail.html | 8 +-- .../resources/templates/rqueue/queues.html | 2 +- .../resources/templates/rqueue/running.html | 4 +- .../resources/templates/rqueue/utility.html | 4 +- .../integration/RqueueViewControllerTest.java | 16 +++--- 11 files changed, 76 insertions(+), 77 deletions(-) create mode 100644 rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DefaultFunction.java diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java index 039302df..6c7078d8 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/config/RqueueListenerBaseConfig.java @@ -33,7 +33,7 @@ import com.github.sonus21.rqueue.utils.pebble.ResourceLoader; import com.github.sonus21.rqueue.utils.pebble.RqueuePebbleExtension; import com.mitchellbosecke.pebble.PebbleEngine; -import com.mitchellbosecke.pebble.loader.Loader; +import com.mitchellbosecke.pebble.spring.extension.SpringExtension; import com.mitchellbosecke.pebble.spring.servlet.PebbleViewResolver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -172,14 +172,13 @@ public RqueueLockManager rqueueLockManager(RqueueStringDao rqueueStringDao) { @Bean public PebbleViewResolver rqueueViewResolver() { - Loader resourceLoader = new ResourceLoader(); PebbleEngine pebbleEngine = new PebbleEngine.Builder() - .extension(new RqueuePebbleExtension()) - .loader(resourceLoader) + .extension(new RqueuePebbleExtension(), new SpringExtension(null)) + .loader(new ResourceLoader()) .build(); PebbleViewResolver resolver = new PebbleViewResolver(pebbleEngine); - resolver.setPrefix("classpath:/templates/rqueue/"); + resolver.setPrefix("templates/rqueue/"); resolver.setSuffix(".html"); return resolver; } diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DateTimeFunction.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DateTimeFunction.java index be85cf76..2ae04557 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DateTimeFunction.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DateTimeFunction.java @@ -25,6 +25,7 @@ import java.util.Map; public class DateTimeFunction implements Function { + public static final String FUNCTION_NAME = "time"; @Override public Object execute( diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DeadLetterQueuesFunction.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DeadLetterQueuesFunction.java index 62cdb20b..39655b06 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DeadLetterQueuesFunction.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DeadLetterQueuesFunction.java @@ -28,6 +28,7 @@ @SuppressWarnings("unchecked") public class DeadLetterQueuesFunction implements Function { + public static final String FUNCTION_NAME = "dlq"; @Override public Object execute( diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DefaultFunction.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DefaultFunction.java new file mode 100644 index 00000000..c3e25e31 --- /dev/null +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/DefaultFunction.java @@ -0,0 +1,45 @@ +/* + * Copyright 2021 Sonu Kumar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + * + */ + +package com.github.sonus21.rqueue.utils.pebble; + +import com.mitchellbosecke.pebble.extension.Function; +import com.mitchellbosecke.pebble.template.EvaluationContext; +import com.mitchellbosecke.pebble.template.PebbleTemplate; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class DefaultFunction implements Function { + + public static final String FUNCTION_NAME = "default"; + + @Override + public Object execute( + Map args, PebbleTemplate self, EvaluationContext context, int lineNumber) { + Object src = args.get("src"); + Object dst = args.get("dst"); + if (src == null) { + return dst; + } + return src; + } + + @Override + public List getArgumentNames() { + return Arrays.asList("src", "dst"); + } +} diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/RqueuePebbleExtension.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/RqueuePebbleExtension.java index 9ce4532f..31246bba 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/RqueuePebbleExtension.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/utils/pebble/RqueuePebbleExtension.java @@ -16,66 +16,19 @@ package com.github.sonus21.rqueue.utils.pebble; -import com.mitchellbosecke.pebble.attributes.AttributeResolver; -import com.mitchellbosecke.pebble.extension.Extension; -import com.mitchellbosecke.pebble.extension.Filter; +import com.mitchellbosecke.pebble.extension.AbstractExtension; import com.mitchellbosecke.pebble.extension.Function; -import com.mitchellbosecke.pebble.extension.NodeVisitorFactory; -import com.mitchellbosecke.pebble.extension.Test; -import com.mitchellbosecke.pebble.operator.BinaryOperator; -import com.mitchellbosecke.pebble.operator.UnaryOperator; -import com.mitchellbosecke.pebble.tokenParser.TokenParser; import java.util.HashMap; -import java.util.List; import java.util.Map; -public class RqueuePebbleExtension implements Extension { - - @Override - public Map getFilters() { - return null; - } - - @Override - public Map getTests() { - return null; - } +public class RqueuePebbleExtension extends AbstractExtension { @Override public Map getFunctions() { Map map = new HashMap<>(); - map.put("dlq", new DeadLetterQueuesFunction()); - map.put("time", new DateTimeFunction()); + map.put(DeadLetterQueuesFunction.FUNCTION_NAME, new DeadLetterQueuesFunction()); + map.put(DateTimeFunction.FUNCTION_NAME, new DateTimeFunction()); + map.put(DefaultFunction.FUNCTION_NAME, new DefaultFunction()); return map; } - - @Override - public List getTokenParsers() { - return null; - } - - @Override - public List getBinaryOperators() { - return null; - } - - @Override - public List getUnaryOperators() { - return null; - } - - @Override - public Map getGlobalVariables() { - return null; - } - - @Override - public List getNodeVisitors() { - return null; - } - - @Override - public List getAttributeResolver() { - return null; - } } diff --git a/rqueue-core/src/main/resources/templates/rqueue/index.html b/rqueue-core/src/main/resources/templates/rqueue/index.html index 97d60991..61d0750f 100644 --- a/rqueue-core/src/main/resources/templates/rqueue/index.html +++ b/rqueue-core/src/main/resources/templates/rqueue/index.html @@ -1,8 +1,8 @@ -{% extends 'classpath:/templates/rqueue/base.html' %} +{% extends 'base' %} {% block main %} -{% include 'classpath:/templates/rqueue/stats_chart.html' %} +{% include 'stats_chart' %}


-{% include 'classpath:/templates/rqueue/latency_chart.html' %} +{% include 'latency_chart' %} {% endblock %} {% block additional_script %} diff --git a/rqueue-core/src/main/resources/templates/rqueue/queue_detail.html b/rqueue-core/src/main/resources/templates/rqueue/queue_detail.html index 148586e6..7db5c74d 100644 --- a/rqueue-core/src/main/resources/templates/rqueue/queue_detail.html +++ b/rqueue-core/src/main/resources/templates/rqueue/queue_detail.html @@ -1,4 +1,4 @@ -{% extends 'classpath:/templates/rqueue/base.html' %} +{% extends 'base' %} {% block main %}
@@ -60,11 +60,11 @@

-{% include 'classpath:/templates/rqueue/stats_chart.html' %} +{% include 'stats_chart' %}
-{% include 'classpath:/templates/rqueue/latency_chart.html' %} +{% include 'latency_chart' %} -{% include 'classpath:/templates/rqueue/data_explorer_modal.html' %} +{% include 'data_explorer_modal' %} {% endblock %} {% block additional_script %} diff --git a/rqueue-core/src/main/resources/templates/rqueue/queues.html b/rqueue-core/src/main/resources/templates/rqueue/queues.html index 35e05960..70bb8952 100644 --- a/rqueue-core/src/main/resources/templates/rqueue/queues.html +++ b/rqueue-core/src/main/resources/templates/rqueue/queues.html @@ -1,4 +1,4 @@ -{% extends 'classpath:/templates/rqueue/base.html' %} +{% extends 'base' %} {% block main %}
diff --git a/rqueue-core/src/main/resources/templates/rqueue/running.html b/rqueue-core/src/main/resources/templates/rqueue/running.html index d79ebf9a..7b3aadfe 100644 --- a/rqueue-core/src/main/resources/templates/rqueue/running.html +++ b/rqueue-core/src/main/resources/templates/rqueue/running.html @@ -1,4 +1,4 @@ -{% extends 'classpath:/templates/rqueue/base.html' %} +{% extends 'base' %} {% block main %}
@@ -6,7 +6,7 @@ {% for h in header %} - {{h}} + {{h}} {% endfor %} diff --git a/rqueue-core/src/main/resources/templates/rqueue/utility.html b/rqueue-core/src/main/resources/templates/rqueue/utility.html index ab678110..af35c4f2 100644 --- a/rqueue-core/src/main/resources/templates/rqueue/utility.html +++ b/rqueue-core/src/main/resources/templates/rqueue/utility.html @@ -1,4 +1,4 @@ -{% extends 'classpath:/templates/rqueue/base.html' %} +{% extends 'base' %} {% block main %}
@@ -78,7 +78,7 @@

Explore Data

-{% include 'classpath:/templates/rqueue/data_explorer_modal.html' %} +{% include 'data_explorer_modal' %} {% endblock %} diff --git a/rqueue-spring/src/test/java/com/github/sonus21/rqueue/spring/tests/integration/RqueueViewControllerTest.java b/rqueue-spring/src/test/java/com/github/sonus21/rqueue/spring/tests/integration/RqueueViewControllerTest.java index d5f2caa2..4b920911 100644 --- a/rqueue-spring/src/test/java/com/github/sonus21/rqueue/spring/tests/integration/RqueueViewControllerTest.java +++ b/rqueue-spring/src/test/java/com/github/sonus21/rqueue/spring/tests/integration/RqueueViewControllerTest.java @@ -65,7 +65,7 @@ void home() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/index.html", pebbleView.getUrl()); + assertEquals("index.html", pebbleView.getUrl()); verifyBasicData(model, null); assertEquals( Arrays.asList(AggregationType.DAILY, AggregationType.WEEKLY, AggregationType.MONTHLY), @@ -84,7 +84,7 @@ void queues() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/queues")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/queues.html", pebbleView.getUrl()); + assertEquals("queues.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.QUEUES); assertEquals("Queues", model.get("title")); assertNotNull(model.get("queues")); @@ -96,7 +96,7 @@ void queueDetail() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/queues/" + jobQueue)).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/queue_detail.html", pebbleView.getUrl()); + assertEquals("queue_detail.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.QUEUES); assertEquals("Queue: " + jobQueue, model.get("title")); assertEquals(jobQueue, model.get("queueName")); @@ -121,7 +121,7 @@ void running() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/running")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/running.html", pebbleView.getUrl()); + assertEquals("running.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.RUNNING); assertEquals("Running Tasks", model.get("title")); assertNotNull(model.get("tasks")); @@ -133,7 +133,7 @@ void scheduled() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/scheduled")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/running.html", pebbleView.getUrl()); + assertEquals("running.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.SCHEDULED); assertEquals("Scheduled Tasks", model.get("title")); assertNotNull(model.get("tasks")); @@ -145,7 +145,7 @@ void dead() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/dead")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/running.html", pebbleView.getUrl()); + assertEquals("running.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.DEAD); assertEquals("Tasks moved to dead letter queue", model.get("title")); assertNotNull(model.get("tasks")); @@ -157,7 +157,7 @@ void pending() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/pending")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/running.html", pebbleView.getUrl()); + assertEquals("running.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.PENDING); assertEquals("Tasks waiting for execution", model.get("title")); assertNotNull(model.get("tasks")); @@ -169,7 +169,7 @@ void utility() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/utility")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("classpath:/templates/rqueue/utility.html", pebbleView.getUrl()); + assertEquals("utility.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.UTILITY); assertEquals("Utility", model.get("title")); assertNotNull(model.get("supportedDataType")); From d10963c1de1539feb6646420fcdeef30298c698c Mon Sep 17 00:00:00 2001 From: Sonu Kumar Date: Wed, 24 Feb 2021 23:11:21 +0530 Subject: [PATCH 6/8] pebble template test fix --- .../integration/RqueueViewControllerTest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/rqueue-spring/src/test/java/com/github/sonus21/rqueue/spring/tests/integration/RqueueViewControllerTest.java b/rqueue-spring/src/test/java/com/github/sonus21/rqueue/spring/tests/integration/RqueueViewControllerTest.java index 4b920911..222b602c 100644 --- a/rqueue-spring/src/test/java/com/github/sonus21/rqueue/spring/tests/integration/RqueueViewControllerTest.java +++ b/rqueue-spring/src/test/java/com/github/sonus21/rqueue/spring/tests/integration/RqueueViewControllerTest.java @@ -65,7 +65,7 @@ void home() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("index.html", pebbleView.getUrl()); + assertEquals("templates/rqueue/index.html", pebbleView.getUrl()); verifyBasicData(model, null); assertEquals( Arrays.asList(AggregationType.DAILY, AggregationType.WEEKLY, AggregationType.MONTHLY), @@ -84,7 +84,7 @@ void queues() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/queues")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("queues.html", pebbleView.getUrl()); + assertEquals("templates/rqueue/queues.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.QUEUES); assertEquals("Queues", model.get("title")); assertNotNull(model.get("queues")); @@ -96,7 +96,7 @@ void queueDetail() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/queues/" + jobQueue)).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("queue_detail.html", pebbleView.getUrl()); + assertEquals("templates/rqueue/queue_detail.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.QUEUES); assertEquals("Queue: " + jobQueue, model.get("title")); assertEquals(jobQueue, model.get("queueName")); @@ -121,7 +121,7 @@ void running() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/running")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("running.html", pebbleView.getUrl()); + assertEquals("templates/rqueue/running.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.RUNNING); assertEquals("Running Tasks", model.get("title")); assertNotNull(model.get("tasks")); @@ -133,7 +133,7 @@ void scheduled() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/scheduled")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("running.html", pebbleView.getUrl()); + assertEquals("templates/rqueue/running.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.SCHEDULED); assertEquals("Scheduled Tasks", model.get("title")); assertNotNull(model.get("tasks")); @@ -145,7 +145,7 @@ void dead() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/dead")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("running.html", pebbleView.getUrl()); + assertEquals("templates/rqueue/running.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.DEAD); assertEquals("Tasks moved to dead letter queue", model.get("title")); assertNotNull(model.get("tasks")); @@ -157,7 +157,7 @@ void pending() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/pending")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("running.html", pebbleView.getUrl()); + assertEquals("templates/rqueue/running.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.PENDING); assertEquals("Tasks waiting for execution", model.get("title")); assertNotNull(model.get("tasks")); @@ -169,7 +169,7 @@ void utility() throws Exception { MvcResult result = this.mockMvc.perform(get("/rqueue/utility")).andReturn(); ModelMap model = result.getModelAndView().getModelMap(); PebbleView pebbleView = (PebbleView) result.getModelAndView().getView(); - assertEquals("utility.html", pebbleView.getUrl()); + assertEquals("templates/rqueue/utility.html", pebbleView.getUrl()); verifyBasicData(model, NavTab.UTILITY); assertEquals("Utility", model.get("title")); assertNotNull(model.get("supportedDataType")); From f1c43c676ca6db9fc03886683e55f18b6ea17881 Mon Sep 17 00:00:00 2001 From: Sonu Kumar Date: Fri, 26 Feb 2021 17:01:51 +0530 Subject: [PATCH 7/8] nonce issue --- .../rqueue/web/controller/RqueueViewController.java | 10 +++++----- .../src/main/resources/templates/rqueue/base.html | 4 ++-- .../src/main/resources/templates/rqueue/index.html | 2 +- .../main/resources/templates/rqueue/queue_detail.html | 2 +- .../src/main/resources/templates/rqueue/utility.html | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/rqueue-core/src/main/java/com/github/sonus21/rqueue/web/controller/RqueueViewController.java b/rqueue-core/src/main/java/com/github/sonus21/rqueue/web/controller/RqueueViewController.java index 3164cca1..393745a2 100644 --- a/rqueue-core/src/main/java/com/github/sonus21/rqueue/web/controller/RqueueViewController.java +++ b/rqueue-core/src/main/java/com/github/sonus21/rqueue/web/controller/RqueueViewController.java @@ -103,14 +103,14 @@ private void addBasicDetails(Model model, HttpServletRequest request) { prefix = xForwardedPrefix + prefix; } model.addAttribute("urlPrefix", prefix); - addNonce(model, "urlNonce"); + // addNonce(model, "urlNonce"); } @SuppressWarnings("unchecked") private void addNonce(Model model, String name) { ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); buffer.putLong(System.nanoTime()); - String nonce = new String(base62.encode(buffer.array())); + String nonce = "nonce-" + new String(base62.encode(buffer.array())); List nonces = (List) model.asMap().get("nonces"); if (nonces == null) { nonces = new ArrayList<>(); @@ -129,7 +129,7 @@ public View index(Model model, HttpServletRequest request, HttpServletResponse r } addBasicDetails(model, request); addNavData(model, null); - addNonce(model, "indexNonce"); + // addNonce(model, "indexNonce"); model.addAttribute("title", "Rqueue Dashboard"); model.addAttribute("aggregatorTypes", Arrays.asList(AggregationType.values())); model.addAttribute("typeSelectors", ChartDataType.getActiveCharts()); @@ -172,7 +172,7 @@ public View queueDetail( rqueueQDetailService.getQueueDataStructureDetail(queueConfig); addBasicDetails(model, request); addNavData(model, NavTab.QUEUES); - addNonce(model, "queueDetailNonce"); + // addNonce(model, "queueDetailNonce"); model.addAttribute("title", "Queue: " + queueName); model.addAttribute("queueName", queueName); model.addAttribute("aggregatorTypes", Arrays.asList(AggregationType.values())); @@ -257,7 +257,7 @@ public View utility(Model model, HttpServletRequest request, HttpServletResponse } addBasicDetails(model, request); addNavData(model, NavTab.UTILITY); - addNonce(model, "utilityNonce"); + // addNonce(model, "utilityNonce"); model.addAttribute("title", "Utility"); model.addAttribute("supportedDataType", DataType.getEnabledDataTypes()); return rqueueViewResolver.resolveViewName("utility", Locale.ENGLISH); diff --git a/rqueue-core/src/main/resources/templates/rqueue/base.html b/rqueue-core/src/main/resources/templates/rqueue/base.html index c4772090..539c67ee 100644 --- a/rqueue-core/src/main/resources/templates/rqueue/base.html +++ b/rqueue-core/src/main/resources/templates/rqueue/base.html @@ -4,7 +4,7 @@ + content="default-src 'self' *.gstatic.com *.googleapis.com 'unsafe-inline' 'unsafe-eval'"> @@ -150,7 +150,7 @@ - {% block additional_script %}{% endblock %} diff --git a/rqueue-core/src/main/resources/templates/rqueue/index.html b/rqueue-core/src/main/resources/templates/rqueue/index.html index 61d0750f..22f51039 100644 --- a/rqueue-core/src/main/resources/templates/rqueue/index.html +++ b/rqueue-core/src/main/resources/templates/rqueue/index.html @@ -6,7 +6,7 @@ {% endblock %} {% block additional_script %} -