Conversation
Introduces an internal MessageBroker SPI in rqueue-core under com.github.sonus21.rqueue.core.spi/ to enable a NATS/JetStream backend in a follow-up commit. RedisMessageBroker is added as a thin delegating implementation backed by the existing RqueueMessageTemplate and DAO paths; behavior on the Redis path is unchanged. Public API additions are additive only: setMessageBroker/getMessageBroker on RqueueMessageTemplateImpl, SimpleRqueueListenerContainerFactory, and RqueueMessageListenerContainer; a new constructor overload on RqueueMessageTemplateImpl. When messageBroker is null (the existing code path) every gate falls back to legacy behavior, so current Redis users see no change. Tests: 461 existing tests + 14 new RedisMessageBrokerDelegationTest cases pass; 8 skipped, 0 failures. Assisted-By: Claude Code
Includes the new rqueue-nats Gradle module in settings.gradle and adds natsVersion (2.25.2) plus testcontainersVersion to the root build. The module's build.gradle declares it as broker-impl-only (rqueue-core + io.nats:jnats); no Spring/Spring Boot deps live here. rqueue-spring and rqueue-spring-boot-starter pick up rqueue-nats and jnats as compileOnly so their @configuration / auto-config classes can reference NATS types behind @ConditionalOnClass without forcing NATS onto current Redis users at runtime. Test-scoped runtime deps let the integration tests exercise both backends. Assisted-By: Claude Code
Implements the MessageBroker SPI for NATS JetStream in the new rqueue-nats module. Includes JetStreamMessageBroker with a fluent Builder, RqueueNatsConfig POJO with stream/consumer defaults, an idempotent NatsProvisioner, and a ServiceLoader-discovered JetStreamMessageBrokerFactory registered under META-INF/services/com.github.sonus21.rqueue.core.spi.MessageBrokerFactory. v1 scope: pull, durable consumers only; immediate enqueue + ack + retry-via-nak; DLQ via MaxDeliver + advisory bridge; dedup via Nats-Msg-Id and the configured Duplicates window; ephemeral consumers reserved for peek; per-broker in-memory inFlight map for ack/nack lookup. enqueueWithDelay throws UnsupportedOperationException; moveExpired is a no-op; capabilities are all false. Tests: 4 unit tests pass (JetStreamMessageBrokerDelayThrowsTest); 7 integration tests gated on Docker via @testcontainers (disabledWithoutDocker = true) — they skip when Docker isn't available and run end-to-end against nats:2.10-alpine -js otherwise. Assisted-By: Claude Code
Phase 3 of the NATS backend wiring extends the listener annotation with an optional consumerName(), introduces ConsumerNameResolver for the "rqueue-<queue>-<bean>#<method>" default, and lets the listener container flag the message handler to skip the "exactly one primary per queue" check when the active broker reports usesPrimaryHandlerDispatch == false. A single WARN is logged for queues with multiple @RqueueHandler methods under such a broker. Cross-handler (queueName, consumerName) collision detection runs at container init for the gated path so boot fails fast. Redis behavior is unchanged: the new flag defaults to true and the container only takes the gated branches when a non-Redis broker is set. Assisted-By: Claude Code
Adds nullable fields (natsStream, natsSubject, natsDlqStream, natsDlqSubject, natsAckWaitOverride, natsMaxDeliverOverride, natsDedupWindow) and resolved* helpers that derive sensible defaults from queueName/visibilityTimeout/numRetry when the override is null. Purely additive: no existing field, ordering, constructor, or method is modified, and the existing equals/hashCode/toString contract is preserved. Assisted-By: Claude Code
…UI for NATS The dashboard service (RqueueQDetailService) now optionally takes a MessageBroker via @Autowired(required=false). When the broker is set: * getQueueDataStructureDetail() prefers MessageBroker.size(QueueDetail) for the pending-queue size; the Redis path is preserved as fallback when no broker is wired. * getExplorePageData() prefers MessageBroker.peek(QueueDetail, off, n) for the ready (LIST) queue. * When capabilities().supportsScheduledIntrospection() is false, the SCHEDULED nav tab and queue-detail entry are suppressed, the explore response for the scheduled queue returns empty rows, and the new additive DataViewResponse#hideScheduledPanel flag is set so the Pebble template can hide the panel. The scheduled menu item in base.html is now wrapped in {% if not hideScheduledPanel %}. * supportsCronJobs() drives the additive hideCronJobs flag the same way for follow-up cron-management UI work. Changes are purely additive: existing constructors, field ordering, and Redis-only behavior are unchanged when no broker bean is present. Assisted-By: Claude Code
Provides Spring Boot auto-configuration that wires a JetStream-backed MessageBroker when rqueue.backend=nats is set and io.nats:jnats is on the classpath. The auto-config sits before RqueueListenerAutoConfig so its broker bean wins; the listener container factory now picks up an optional MessageBroker via ObjectProvider, leaving the Redis-only default path identical when the property/classpath conditions don't match. Assisted-By: Claude Code
Gives non-Boot Spring users a way to opt into the JetStream backend without depending on Spring Boot. The new Backend enum (AUTO, REDIS, NATS) on @EnableRqueue picks which configuration to import; AUTO preserves the current Redis-only path unless jnats is on the classpath and rqueue.backend=nats. NATS forces the import, REDIS skips it. A small NatsBackendCondition keeps the AUTO branch lazy. Assisted-By: Claude Code
CLAUDE.md spells out that AI tools (Claude, Copilot, etc.) must not appear as Co-Authored-By on commits — humans only — but an Assisted-By: <tool> trailer is acceptable for noting the assistance without claiming co-authorship. Future AI sessions read this file cold and align their commit templates accordingly. Assisted-By: Claude Code
Phase 3.5 introduces a per-listener poller that drives the runtime path for capability-gated brokers (NATS / JetStream). One poller is bound to a single (queueDetail, consumerName, handlerMethod) triple and runs an independent loop: pop a batch with a short wait, deserialize each payload through the configured MessageConverter, invoke the bound bean method via reflection, then ack on success or nack with the configured TaskExecutionBackOff delay on exception. Direct reflection dispatch (Option B in the phase notes) keeps the broker path narrow and avoids the primary/secondary handler mapping that NATS-style backends do not honor. Concurrency is intentionally a single thread per (queue, consumerName) for v1; JetStream's MaxAckPending already controls in-flight distribution. Container wiring lands in the next commit. Assisted-By: Claude Code
When the active MessageBroker reports usesPrimaryHandlerDispatch=false
the container now skips the legacy Redis-side wiring (startQueue /
startGroup) and instead instantiates one BrokerMessagePoller per
(queue, consumerName) pair resolved from registered @RqueueListener
methods, submitting each to a minimal task executor. The legacy code
path is unchanged when no broker is set or the broker reports
REDIS_DEFAULTS capabilities.
Lifecycle integration:
* doStop signals each poller to exit and waits up to maxWorkerWaitTime
* doDestroy closes the broker if it implements AutoCloseable
* initialize() bypasses worker thread-map creation on the broker path
since pollers run on their own task executor
@RqueueListener.concurrency > 1 logs a single INFO and is honored as
a single-thread poller in v1; JetStream MaxAckPending governs in-flight
distribution. Priority queues on the broker path are out of scope for
Phase 3.5 and remain a follow-up.
Assisted-By: Claude Code
Adds NatsBackendEndToEndIT under rqueue-spring-boot-starter with a Testcontainers-managed nats:2.10-alpine -js, an @RqueueListener, and the standard RqueueMessageEnqueuer. The test exercises the intended path: enqueue -> JetStreamMessageBroker.enqueue -> stream -> poller -> listener -> ack. The test is currently @disabled because the producer enqueue path (BaseMessageSender#enqueue + RqueueMessageMetadataService) is not yet routed through MessageBroker; with rqueue.backend=nats and no Redis instance available, enqueue still hits Redis. The test is left on disk (compiled, skipped) so the wiring fix has a ready-made acceptance test; the @disabled message documents what to fix. Adds testcontainers:junit-jupiter to the starter test classpath since the test uses @testcontainers / @container. Assisted-By: Claude Code
Previously the broker poller branch spawned exactly one BrokerMessagePoller per (queue, consumerName) pair and logged an INFO advising users that concurrency was not honored. JetStream's MaxAckPending controls in-flight distribution but per-thread parallelism still requires multiple subscribers bound to the same durable consumer. This change spawns N pollers per (queue, consumerName) where N is the upper bound of the listener's concurrency setting. All threads share the same durable consumer; JetStream load-balances messages across them and shares a single MaxAckPending budget. Elastic ramping (min < max) is documented as not yet implemented — the container always uses a fixed pool sized to max. The default task executor's pool is now sized to the sum of resolved thread counts so every poller has a dedicated worker. Assisted-By: Claude Code
Adds two additive default methods to MessageBroker so backends can route on a per-priority basis without breaking existing implementations: - enqueue(QueueDetail, String priority, RqueueMessage): defaults to the unsuffixed enqueue (Redis already encodes priority in the queue name). - pop(QueueDetail, String priority, String consumerName, int, Duration): defaults to the unsuffixed pop. JetStreamMessageBroker overrides both to derive priority-specific streams (rqueue-<queue>-<priority>) and subjects (rqueue.<queue>.<priority>). The listener container now expands a queue's listener-declared priority map into one BrokerMessagePoller-set per priority bucket, with consumer names suffixed by "-<priority>". Combined with concurrency, a queue with N priorities and concurrency=K spawns N*K pollers, each bound to its own priority-specific durable consumer. Weighted/strict priority dispatch is intentionally out of scope; relative fairness is left to thread scheduling. Cross-queue priorityGroup support is not implemented for NATS in v1; a single WARN is logged when a listener declares one. Elastic concurrency ramping is also still deferred; the fixed-pool-at-max behavior is reused. QueueDetail gains resolvedNatsStreamForPriority and resolvedNatsSubjectForPriority helpers parallel to the existing resolvedNats* derivations. The enqueuer side: RqueueMessageEnqueuerImpl.enqueueWithPriority now keeps using the suffixed queue name for Redis (unchanged) but, when the underlying RqueueMessageTemplate exposes a non-primary-handler-dispatch broker, switches to passing the original queue name plus the priority hint through BaseMessageSender.pushMessage so the broker's priority-aware overload routes to the correct subject. Assisted-By: Claude Code
Add additive default `enqueueReactive` and `enqueueWithDelayReactive` methods on the MessageBroker SPI that wrap the blocking calls in Mono.fromRunnable. Override both on JetStreamMessageBroker: `enqueueReactive` uses `JetStream.publishAsync(...)` adapted via Mono.fromFuture so the publish does not block the calling thread, and `enqueueWithDelayReactive` returns Mono.error with the same message as the synchronous variant. Assisted-By: Claude Code
Add a setMessageBroker hook on ReactiveRqueueMessageEnqueuerImpl so the reactive enqueue path can delegate to a MessageBroker SPI implementation (e.g. JetStream) instead of the legacy reactive Redis template. When no broker bean is present the impl keeps the existing ReactiveScriptExecutor path, preserving behavior for Redis users. Wire the setter from both the Spring Boot autoconfig and the non-Boot RqueueListenerConfig via ObjectProvider<MessageBroker>, mirroring the pattern already used for the listener container factory. Add reactor-test as a test-only dependency on rqueue-core and rqueue-nats to support the new StepVerifier-based tests. Tests: - ReactiveRqueueMessageEnqueuerBrokerRoutingTest verifies broker routing for both immediate and delayed enqueue, plus fallback to the redis template when no broker is configured. - JetStreamMessageBrokerReactiveEnqueueIT (Testcontainers, gated on Docker) publishes 5 messages reactively and asserts delayed reactive enqueue surfaces UnsupportedOperationException. Assisted-By: Claude Code
When the active MessageBroker reports !usesPrimaryHandlerDispatch (e.g. NATS/JetStream), short-circuit storeMessageMetadata so the dashboard's informational HASH write to Redis is not attempted on a NATS-only deployment that may have no Redis on the classpath. Reactive callers get Mono.just(true) to mimic a successful save. Assisted-By: Claude Code
The producer-side gap is now closed: BaseMessageSender routes through the MessageBroker SPI when the active broker advertises !usesPrimaryHandlerDispatch(), and storeMessageMetadata short-circuits on the same flag. The sync RqueueMessageEnqueuer / @RqueueListener path exercised by this test no longer needs Redis, so we drop @disabled. Testcontainers' disabledWithoutDocker keeps the test skipping gracefully on hosts without Docker. Assisted-By: Claude Code
Adds a docs-overrides.css with a warmer accent for the .note callout in dark mode; the default blue/purple tone clashes with the surrounding content. Twelve lines, all CSS, no template wiring needed. Assisted-By: Claude Code
Adds @tag("nats") meta-annotations (@NatsIntegrationTest and @NatsUnitTest) in rqueue-nats and applies them to the JetStream test files; tags RqueueNatsAutoConfigTest, RqueueNatsListenerConfigTest, and NatsBackendEndToEndIT directly. NatsUnitTest deliberately omits the MockitoExtension because the existing tests use Mockito.mock() directly and adding the extension would activate strict-stubbing. Adds a nats_integration_test job to java-ci.yaml that runs :rqueue-nats:test :rqueue-spring-boot-starter:test :rqueue-spring:test with -DincludeTags=nats. Docker is preinstalled on ubuntu-latest, so Testcontainers picks it up automatically and the JetStream ITs run against nats:2.10-alpine -js. Coverage from this job is fed into the existing coverage_report job. Local verification: the same gradle invocation reports 13 tests run, 9 skipped (Docker-gated ITs without local Docker), 0 failures. Assisted-By: Claude Code
Drops the @tag("integration") trailer from @NatsIntegrationTest meta and NatsBackendEndToEndIT so the existing integration_test and reactive_integration_test jobs (filtered by -DincludeTags=integration) no longer try to run NATS tests on a Redis-shaped runner. NATS tests now match only the dedicated nats_integration_test job's -DincludeTags=nats filter. This fixes the integration_test and reactive_integration_test job failures that landed alongside the previous CI commit. The nats_integration_test job is unchanged. Assisted-By: Claude Code
Assisted-By: Claude Code
Assisted-By: Claude Code
The dashboard controller chain (RqueueRestController → RqueueDashboardChartServiceImpl → RqueueQStatsDaoImpl → RqueueConfig) currently still hard-requires a RedisConnectionFactory bean even when rqueue.backend=nats, so excluding DataRedisAutoConfiguration left the Spring context unable to load on the CI runner. Until those beans are made conditional on the broker's usesPrimaryHandlerDispatch capability (tracked as a v1.x follow-up), this e2e test starts an embedded Redis on a free port purely to satisfy the bean graph. The actual produce-and-consume flow runs entirely through JetStream — Redis is never touched by the message path. Assisted-By: Claude Code
…atchers Assisted-By: Claude Code
Adds three NATS-tagged Spring Boot end-to-end integration tests plus a shared AbstractNatsBootIT base class that lifts the Testcontainers + @DynamicPropertySource boilerplate. - NatsConcurrencyE2EIT: proves @RqueueListener(concurrency="3") yields >1 parallel handler invocations on JetStream pull subscribers. - NatsConsumerNameOverrideE2EIT: confirms an explicit consumerName attribute lands on the JetStream stream as a durable consumer with that exact name (queried via JetStreamManagement). - NatsReactiveEnqueueE2EIT: enqueues 5 messages via ReactiveRqueueMessageEnqueuer (Flux.merge) and verifies a sync listener receives all 5; requires rqueue.reactive.enabled=true. Assisted-By: Claude Code
- NatsPriorityQueuesE2EIT: a single @RqueueListener with priority="high=10,low=1" consumes 5 high + 5 low messages enqueued via RqueueMessageEnqueuer.enqueueWithPriority and we assert per- priority counts come out exact. - NatsMultipleListenersOnSameQueueE2EIT: documents the desired fan-out semantics across two @RqueueListener methods on the same queue, but is @disabled because the default WorkQueue stream retention only allows a single filter-overlapping consumer; enable once the broker supports Limits/Interest retention per queue. Assisted-By: Claude Code
…rker registry Rename natsConsumerName -> consumerName to make the concept broker-agnostic. Introduce pollerKey (queue##consumer) in RqueueMessageListenerContainer to prevent the second consumer of a multi-consumer queue being skipped by the bare-name dedup check. Wire worker registry heartbeats and capacity-exhausted tracking through consumerTrackingKey so each consumer is reported separately. Add NATS stream retention policy and a 14-day maxAge default; wire the message broker onto RqueueMessageTemplateImpl at container start for non-Redis publish paths. Extract BaseListener/JobListener in the spring-boot example. Assisted-By: Claude Code
rqueueMessageHandler now requires a MessageBroker argument (added to wire primary-handler-dispatch capability). Update both test classes to supply a mocked MessageBroker stubbed with REDIS_DEFAULTS capabilities. Assisted-By: Claude Code
1. Default retention WorkQueue (was Limits) Streams must use WorkQueue retention so that acked messages are removed from the stream and broker.size() drains to 0. The peek IT already sets Limits explicitly so it is unaffected. Also update RqueueNatsProperties so the Spring Boot auto-config matches. 2. provisionDlq always creates the DLQ stream autoCreateDlqStream gates automatic bootstrap provisioning, not explicit calls. provisionDlq() is opt-in by the caller; guard it with ensureStream directly instead of ensureDlqStream, which also checked the flag. 3. Priority stream names use underscore suffix (PriorityUtils convention) streamFor/subjectFor(q, priority) used a dash separator (pq-high) but the poller's expanded QueueDetail.name uses the PriorityUtils suffix (pq_high). Align both to PriorityUtils.getSuffix() so enqueue and pop target the same stream. Update NatsStreamValidator's priority loop and the unit test assertion accordingly. Assisted-By: Claude Code
Default stream retention stays Limits (broker-agnostic default). The enqueuePopAck_drainsStream test requires WorkQueue semantics so it now sets the policy explicitly on its own config, matching the pattern already used by JetStreamMessageBrokerPeekIT. Assisted-By: Claude Code
Each priority sub-queue (pq_high, pq_low) is registered as its own
QueueDetail in EndpointRegistry and processed as a mainStream entry,
which creates exactly one consumer per stream. The priority loop that
runs for the base queue (pq) was calling tryEnsureConsumer a second
time on those same streams, which fails with error 10099 on WorkQueue
streams ("multiple non-filtered consumers not allowed"). Remove the
consumer creation from the priority loop; stream ensure is sufficient
and safe (idempotent via the provisioner cache).
Assisted-By: Claude Code
… provisioning - Add QueueType enum (QUEUE = WorkQueue retention, STREAM = Limits/fan-out) - Add queueMode() attribute to @RqueueListener, default QUEUE - Thread QueueType through MappingInformation → QueueDetail builder - MessageBroker.onQueueRegistered() hook; JetStreamMessageBroker overrides it to provision the stream immediately on registerQueue() calls (producer-only mode) - NatsProvisioner.ensureStream(name, subjects, QueueType) picks WorkQueue vs Limits retention; warns and preserves existing config on mismatch - NatsStreamValidator and JetStreamMessageBroker pass q.getType() to provisioner - RqueueRedisConfigImportSelector: lazy-load RqueueRedisListenerConfig via ImportSelector so excluding rqueue-redis no longer crashes Spring at startup - Fix JetStreamMessageBrokerPeekIT and IndependentConsumersIT to use QueueType instead of the now-bypassed setRetention() config workaround - Add JetStreamQueueModeIT: 5 E2E contracts covering stream retention, consumer reuse/position preservation, competing-consumer delivery, and fan-out delivery Assisted-By: Claude Code
…d version bump - RqueueEndpointManager: add registerQueue(name, QueueType, priorities) overload; old no-arg signature preserved as default method for backward compat - RqueueEndpointManagerImpl: implements new QueueType-aware registration - GenericMessageConverter: add constructor accepting a custom ObjectMapper - JetStreamMessageBrokerProducerOnlyIT: refactor to domain event POJOs - build.gradle: bump version to 4.0.0-SK1 Assisted-By: Claude Code
…eSender - BaseMessageSender, RqueueEndpointManagerImpl, RqueueMessageEnqueuerImpl, RqueueMessageManagerImpl, ReactiveRqueueMessageEnqueuerImpl now take MessageBroker as a constructor arg instead of reading it off the template. - enqueue/storeMessageMetadata/notifyBrokerQueueRegistered route through the injected broker unconditionally; the Redis-vs-NATS dispatch lives inside each broker implementation. - RedisMessageBroker overrides enqueueReactive/enqueueWithDelayReactive so reactive callers stay on the reactive Redis driver. - RqueueMessageTemplateImpl no longer holds a MessageBroker; the setMessageBroker wiring in RqueueListenerAutoConfig / RqueueListenerConfig / RqueueMessageListenerContainer is removed in favor of injecting the broker bean directly into the *Impl beans. - Tests updated to construct *Impl beans with an explicit broker; new RqueueMessageEnqueuerBrokerRoutingTest pins the non-reactive routing path. Assisted-By: Claude Code
- MessageBroker SPI: new default no-op validateQueueName(String) hook. - JetStreamMessageBroker overrides it to reject queue names containing '.', '*', '>' or whitespace. NATS subjects use '.' as a hierarchy separator and stream / consumer names disallow it outright, so a silent accept turned into an opaque driver-side rejection at first publish; now it fails loudly at registration with a message that points users at '-' / '_'. - BaseMessageSender.registerQueueInternal and RqueueMessageListenerContainer.initializeQueueRegistry both call validateQueueName, so both the explicit RqueueEndpointManager.registerQueue path and the @RqueueListener bootstrap path validate. - NatsProvisioner.ensureStream gains a description overload; the broker passes "rqueue queue: <name>" (and "(priority=<p>)" / "rqueue DLQ for queue: <name>" for the priority and DLQ variants) so operators can map a stream back to the queue that created it via `nats stream info`. - NatsStreamValidator passes the same description on the bootstrap path. Tests: JetStreamMessageBrokerQueueNameValidationTest pins the character-rejection rules; JetStreamMessageBrokerStreamDescriptionTest pins the description format on enqueue / onQueueRegistered / priority enqueue paths; RqueueEndpointManagerImplTest gains a regression covering broker-validation propagation through registerQueue. Assisted-By: Claude Code
Map QueueDetail.visibilityTimeout to JetStream ackWait and numRetry to maxDeliver (numRetry + 1, with Integer.MAX_VALUE as the unlimited sentinel) when the durable pull consumer is provisioned. Falls back to RqueueNatsConfig.consumerDefaults when the per-queue value is unset. Resolution lives in JetStreamMessageBroker.resolveAckWait / resolveMaxDeliver and is used by both popInternal and the bootstrap NatsStreamValidator so the consumer is created with the right config upfront (provisioner only logs a warning on existing-config drift). Also drops dead, never-set NATS-related fields from QueueDetail (natsStream, natsSubject, natsDlqStream, natsDlqSubject, natsMaxDeliverOverride, natsDedupWindow) and their resolved* helpers, plus the corresponding test. Broker DLQ name helpers now compute directly from prefix + suffix. Assisted-By: Claude Code
…weep - RqueueMessagePoller now forwards the configured pollingInterval to MessageBroker.pop instead of Duration.ZERO, letting JetStream long-poll rather than spinning $JS.API.CONSUMER.MSG.NEXT requests at full speed. Covered by a new test in RqueueMessageListenerContainerBrokerBranchTest. - RqueueNatsAutoConfig wires RqueueConfig into NatsStreamValidator so producer-only deployments skip durable consumer creation. - StringUtils-based null/empty checks in RqueueNatsAutoConfig. - Copyright headers normalized to 2026 across the NATS-touched files. Assisted-By: Claude Code
Fixed javadoc compilation warnings by: - Removing @link tags for cross-module references that aren't resolvable during module-specific javadoc generation (RqueueListenerConfig refs) - Converting method-level @link references to inline code snippets (RqueueWorkerInfo#getWorkerId, ConsumerDefaults methods) - Using code font formatting for methods not visible to javadoc compiler All javadoc generation for core, redis, and nats modules now passes without warnings. Assisted-By: Claude Code
Added or improved class-level documentation for: - RqueueMessage: Detailed explanation of message envelope structure, timing/scheduling fields, failure tracking, and periodic task support. - QueueDetail: Configuration metadata for listener behavior including polling, error handling, dead-letter queues, and priority sub-queues. - RqueueMessageHandler: Internal handler for @RqueueListener method invocation, exception routing, and type-safe argument injection. Assisted-By: Claude Code
…flict The test was configuring both redisConnectionFactory and a non-Redis MessageBroker, which violates the validation in SimpleRqueueListenerContainerFactory that ensures exactly one transport is configured. Fixed by setting the messageBroker directly instead of the Redis connection factory when testing with a non-Redis broker. Assisted-By: Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Please include a summary of the changes and the related issue. Please also include relevant motivation and context. List any dependencies that are required for this change.
Fixes # (issue)
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
Test Configuration:
Checklist: