You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pr@cassandra.apache.org by GitBox <gi...@apache.org> on 2022/03/29 23:44:35 UTC

[GitHub] [cassandra-sidecar] yifan-c commented on a change in pull request #27: CASSANDRASC-35: Add the CONTRIBUTING.md doc with guidelines and best practices

yifan-c commented on a change in pull request #27:
URL: https://github.com/apache/cassandra-sidecar/pull/27#discussion_r837994986



##########
File path: CONTRIBUTING.md
##########
@@ -0,0 +1,329 @@
+# Contributing to Apache Cassandra Sidecar
+
+We warmly welcome and appreciate contributions from the community.
+
+## Table of Contents
+
+* [How to Contribute](#how-to-contribute)
+  * [Discuss](#discuss)
+  * [Create a Ticket](#ticket)
+* [Source Code Best Practices](#best-practices)
+  * [Asynchronous Programming](#async-programming)
+  * [Thread Pool Model](#thread-pools)
+  * [One-shot Timers and Periodic Timers](#timers)
+  * [RestEasy Integration](#resteasy)
+  * [Dependency Injection](#guice)
+  * [Handler Chaining](#chaining-handlers)
+  * [Asynchronous Handlers](#async-handlers)
+  * [Future Composition](#future-composition)
+  * [Failure Handling](#failure-handling)
+* [Source Code Style](#source-code-style)
+
+## <a name="how-to-contribute"></a>How to Contribute
+
+### <a name="discuss"></a>Discuss
+
+Find an existing issue on Jira, or start a new discussing in the Apache Cassandra mailing list.
+
+### <a name="ticket"></a>Create a Ticket
+
+Before creating a ticket, please take the time to [research first](#discuss).
+
+If you are creating a new Jira after a discussion on the Apache Cassandra mailing list, please provide a
+self-sufficient description in the ticket. This is certainly extra work, but Jira is the place where we capture
+important design discussions and decisions that can often be referenced after the fix version, to understand
+the origin of a feature, understand design decisions, and so on.
+
+When ready create a Jira ticket.
+
+## <a name="best-practices"></a>Source Code Best Practices
+
+The Apache Cassandra Sidecar project uses the [vertx](https://vertx.io) toolkit. It uses the asynchronous and
+reactive programming paradigm. This allows for Sidecar to scale up as workloads grow, as well as resiliency when
+failures arise.
+
+<a name="traditional-app-server"></a>
+In a traditional application server, a pool of threads is used to receive request. Each request is handled by a
+distinct thread. This model is well suited for small-medium workloads. As workloads grow, applications need to scale
+horizontally because of hardware limits on the number of threads that can be created.
+
+### <a name="async-programming"></a>Asynchronous Programming
+
+In the Asynchronous Programming model, the same hardware is able to handle more requests. This model uses fewer threads
+to process incoming connections. When blocking I/O operations occur, the thread moves on to the next task (handling
+a different request for example), and then once the I/O operation has completed the thread will come back to the
+initial task.
+
+Vertx multiplexes concurrent workloads using event loops. This allows taking advantage of the existing hardware more
+effectively to handle more requests.
+
+Any blocking I/O or CPU intensive processing needs to be handled outside the event loop threads. NEVER BLOCK THE
+EVENT LOOP THREAD!
+
+### <a name="thread-pools"></a>Thread Pool Model
+
+Vertx uses different thread pools for internal processing. By default, vertx will use the event loop thread pool,
+the worker thread pool, and the internal worker thread pool.
+
+#### The event loop thread pool (i.e. vert.x-eventloop-thread-1)
+
+The event loop thread pool threads handle events for processing. When the event comes in, it is dispatched to a
+handler. It is expected that the processing will be complete quickly per event. If it doesn't you will see log
+entries warning you that the event loop thread has been blocked. Vertx provisions a thread to detect blocked threads
+in the execution.
+
+```
+Thread vertx-eventloop-thread-3 has been blocked for 20458 ms
+```
+
+If you see log entries like the one above, make sure to audit your code to understand your code and what is
+causing your code to block the event pool thread. Consider moving the blocking I/O operations or CPU-intensive
+operations to a worker thread pool.
+
+#### The worker thread pool (i.e. vert.x-worker-thread-1)
+
+This thread pool is dedicated to handling blocking I/O operations or CPU-intensive operations that might block
+event loop threads. By default, the thread pool has 20 threads. The number of worker threads can be configured
+when configuring the `DeploymentOptions` for vertx.
+
+#### The internal worker thread pool (i.e. vert.x-internal-worker-thread-1)
+
+An internal worker thread pool used by vertx for internal operations. Similarly to the worker thread pool, the
+internal worker thread pool has 20 threads by default. Do not use this thread pool directly, use the worker
+thread pool instead.
+
+### <a href="timers"></a>One-shot Timers and Periodic Timers
+
+Use vertx APIs to set one-shot timers and periodic timers. If you need to execute a one-time operation in the future,
+or if you need to run periodic operations within vertx, an API is available. These timers utilize vertx provisioned
+threads that are managed internal by vertx. For example
+
+```java
+logger.debug("Retrying streaming after {} millis", millis);
+vertx.setTimer(millis, t -> acquireAndSend(context, filename, fileLength, range, startTime));
+```
+
+### <a href="resteasy"></a>RestEasy Integration
+
+The Apache Cassandra Sidecar project uses vertx-resteasy, and is the preferred method to provision endpoints. The
+exception to the rule is when you require access to low-level APIs that are not available through RestEasy. Here's
+an example of a simple RestEasy handler.
+
+```java
+@Path("/api/v1/time-skew")
+public class TimeSkewHandler {
+  private final TimeSkewInfo info;
+
+  @Inject
+  public TimeSkewHandler(TimeSkewInfo info) {
+    info = info;
+  }
+
+  @GET
+  public TimeSkewResponse getTimeSkewResponse() {
+    return new TimeSkewResponse(System.currentTimeMillis(), info.allowableSkewInMinutes());;
+  }
+}
+```
+
+### <a href="guice"></a>Dependency Injection
+
+The Apache Cassandra Sidecar project uses Guice for handling the object interdependency. When a class encapsulates
+some functionality that is then used by a different class in the system, we use Guice for dependency injection.
+
+When a different implementation can be provided in the future, prefer using an interface and a default implementation
+that can be later switched transparently without affecting the classes that depend on it.
+
+Prefer creating concrete classes over utility methods. The concrete classes can be managed as a
+[Singleton](https://en.wikipedia.org/wiki/Singleton_pattern) if they do not have external dependencies that might
+change their behavior based on the configuration.
+
+Here's an example of a class being managed by Guice.
+
+```java
+/**
+ * Verifies the checksum of a file
+ */
+public interface ChecksumVerifier {
+  Future<Boolean> verify(String expectedhash, String filename);
+}
+```
+
+Let's say we support `MD5` for checksum verification, our implementation can look like this:
+
+```java
+public class MD5ChecksumVerifier implements ChecksumVerifier {
+    public Future<Boolean> verify(String expectedhash, String filename) {
+        return fs.open(filename, new OpenOptions())
+                 .compose(this::calculateMD5)
+                 .compose(computedChecksum -> {
+                     if (!expectedHash.equals(computedChecksum))
+                         return Future.failedFuture();
+                     return Future.succeededFuture(true);
+                 });
+    }
+  }
+```
+
+A new implementation of `CheksumVerifier` that uses a different hashing algorithm can be injected later.

Review comment:
       ```suggestion
   A new implementation of `ChecksumVerifier` that uses a different hashing algorithm can be injected later.
   ````




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org
For additional commands, e-mail: pr-help@cassandra.apache.org