Skip to content

Commit

Permalink
feat: Add API for gRPC. Compiler support later. (#266)
Browse files Browse the repository at this point in the history
Signed-off-by: Richard Bair <rbair23@users.noreply.github.com>
  • Loading branch information
rbair23 authored Aug 21, 2024
1 parent 17c2595 commit 8520b99
Show file tree
Hide file tree
Showing 10 changed files with 1,917 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pbj-core/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Version number
version=0.9.2-SNAPSHOT
version=0.9.3-SNAPSHOT

# Need increased heap for running Gradle itself, or SonarQube will run the JVM out of metaspace
org.gradle.jvmargs=-Xmx2048m
Expand Down
1 change: 1 addition & 0 deletions pbj-core/pbj-runtime/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ testModuleInfo {
requires("org.junit.jupiter.api")
requires("org.junit.jupiter.params")
requires("org.mockito")
requires("org.mockito.junit.jupiter")
requiresStatic("com.github.spotbugs.annotations")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright (C) 2024 Hedera Hashgraph, LLC
*
* 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
*
* http://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.hedera.pbj.runtime.grpc;

import static java.util.Objects.requireNonNull;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

/**
* Thrown by an application when handling a gRPC request if the request fails. The status will be one of the canonical
* gRPC statuses, and must be specified. This is returned back to the gRPC client. The message is optional and will be
* returned to the client if specified. The cause is not returned to the client, but is used for debugging purposes.
*/
public class GrpcException extends RuntimeException {
/** The GRPC Status to return to the client */
private final @NonNull GrpcStatus status;

/**
* Create a new exception with the given status.
* @param status the status of the exception
*/
public GrpcException(@NonNull final GrpcStatus status) {
this(status, null, null);
}

/**
* Create a new exception with the given status and message.
* @param status the status of the exception
* @param message the message of the exception
*/
public GrpcException(@NonNull final GrpcStatus status, @Nullable final String message) {
this(status, message, null);
}

/**
* Create a new exception with the given status and cause.
* @param status the status of the exception
* @param cause the cause of the exception
*/
public GrpcException(@NonNull final GrpcStatus status, @Nullable final Throwable cause) {
this(status, null, cause);
}

/**
* Create a new gRPC Exception.
* @param status the status of the exception
* @param message the message of the exception
* @param cause the cause of the exception
*/
public GrpcException(
@NonNull final GrpcStatus status, @Nullable final String message, @Nullable final Throwable cause) {
super(message, cause);
this.status = requireNonNull(status);
if (status == GrpcStatus.OK) {
throw new IllegalArgumentException("status cannot be OK");
}
}

/**
* Get the status of the exception.
* @return the status of the exception
*/
@NonNull
public final GrpcStatus status() {
return status;
}

/**
* Get the message of the exception.
* @return the message of the exception
*/
@Nullable
@Override
public String getMessage() {
return super.getMessage();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright (C) 2024 Hedera Hashgraph, LLC
*
* 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
*
* http://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.hedera.pbj.runtime.grpc;

/**
* Status codes for gRPC. These are added to a {@link GrpcException} when an error occurs. The ordinal of the enum
* <strong>exactly matches</strong> the status code in the gRPC protocol. The order in which these enums are defined
* is critical.
*
* @see <a href="https://grpc.github.io/grpc/core/md_doc_statuscodes.html">GRPC Status codes</a>
*/
public enum GrpcStatus {
/**
* The operation completed successfully.
*/
OK, // 0
/**
* The operation was cancelled (typically by the caller).
*/
CANCELLED, // 1
/**
* Unknown error. An example of where this error may be returned is if a Status value received from another
* address space belongs to an error-space that is not known in this address space. Also, errors raised by APIs
* that do not return enough error information may be converted to this error.
*/
UNKNOWN, // 2
/**
* Client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. INVALID_ARGUMENT
* indicates arguments that are problematic regardless of the state of the system (e.g., a malformed file name).
*/
INVALID_ARGUMENT, // 3
/**
* Deadline expired before operation could complete. For operations that change the state of the system, this
* error may be returned even if the operation has completed successfully. For example, a successful response
* from a server could have been delayed long enough for the deadline to expire.
*/
DEADLINE_EXCEEDED, // 4
/**
* Some requested entity (e.g., file or directory) was not found.
*/
NOT_FOUND, // 5
/**
* Some entity that we attempted to create (e.g., file or directory) already exists.
*/
ALREADY_EXISTS, // 6
/**
* The caller does not have permission to execute the specified operation. PERMISSION_DENIED must not be used for
* rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED instead for those errors).
* PERMISSION_DENIED must not be used if the caller cannot be identified (use UNAUTHENTICATED instead for those
* errors).
*/
PERMISSION_DENIED, // 7
/**
* Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space.
*/
RESOURCE_EXHAUSTED, // 8
/**
* Operation was rejected because the system is not in a state required for the operation's execution. For example,
* directory to be deleted may be non-empty, an `rmdir` operation is applied to a non-directory, etc.
*
* <p>A litmus test that may help a service implementor in deciding between FAILED_PRECONDITION, ABORTED, and
* UNAVAILABLE:<br/>
* (a) Use UNAVAILABLE if the client can retry just the failing call.<br/>
* (b) Use ABORTED if the client should retry at a higher-level<br/>
* (e.g., restarting a read-modify-write sequence).<br/>
* (c) Use FAILED_PRECONDITION if the client should not retry until<br/>
* the system state has been explicitly fixed. E.g., if an `rmdir`<br/>
* fails because the directory is non-empty, FAILED_PRECONDITION<br/>
* should be returned since the client should not retry unless<br/>
* they have first fixed up the directory by deleting files from it.<br/>
*/
FAILED_PRECONDITION, // 9
/**
* The operation was aborted, typically due to a concurrency issue like sequencer check failures, transaction
* aborts, etc.
*
* <p>See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE.
*/
ABORTED, // 10
/**
* Operation was attempted past the valid range. E.g., seeking or reading past end of file.
*
* <p>Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system state changes.
* For example, a 32-bit file system will generate INVALID_ARGUMENT if asked to read at an offset that is not in
* the range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from an offset past the current
* file size.
*
* <p>There is a fair bit of overlap between FAILED_PRECONDITION and OUT_OF_RANGE. We recommend using OUT_OF_RANGE
* (the more specific error) when it applies so that callers who are iterating through a space can easily look for
* an OUT_OF_RANGE error to detect when they are done.
*/
OUT_OF_RANGE, // 11
/**
* Operation is not implemented or not supported/enabled in this service.
*/
UNIMPLEMENTED, // 12
/**
* Internal errors. Means some invariants expected by underlying system has been broken. If you see one of these
* errors, something is very broken.
*/
INTERNAL, // 13
/**
* The service is currently unavailable. This is a most likely a transient condition and may be corrected by
* retrying with a backoff. Note that it is not always safe to retry non-idempotent operations.
*
* <p>See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE.
*/
UNAVAILABLE, // 14
/**
* Unrecoverable data loss or corruption.
*/
DATA_LOSS, // 15
/**
* The request does not have valid authentication credentials for the operation.
*/
UNAUTHENTICATED // 16
}
Loading

0 comments on commit 8520b99

Please sign in to comment.