Convert call quality gRPC service to new error model

This commit is contained in:
Ravi Khadiwala
2026-01-26 12:52:52 -06:00
committed by ravi-signal
parent 517c5b8056
commit 8023a9346f
8 changed files with 50 additions and 24 deletions

View File

@@ -29,6 +29,7 @@ import org.whispersystems.textsecuregcm.auth.AuthenticatedDevice;
import org.whispersystems.textsecuregcm.filters.RemoteAddressFilter;
import org.whispersystems.textsecuregcm.limits.RateLimitedByIp;
import org.whispersystems.textsecuregcm.limits.RateLimiters;
import org.whispersystems.textsecuregcm.metrics.CallQualityInvalidArgumentsException;
import org.whispersystems.textsecuregcm.metrics.CallQualitySurveyManager;
@Path("/v1/call_quality_survey")
@@ -73,7 +74,7 @@ public class CallQualitySurveyController {
try {
callQualitySurveyManager.submitCallQualitySurvey(submitCallQualitySurveyRequest, remoteAddress, userAgentString);
} catch (final IllegalArgumentException e) {
} catch (final CallQualityInvalidArgumentsException e) {
throw new WebApplicationException(e.getMessage(), 422);
}
}

View File

@@ -12,6 +12,7 @@ import org.signal.chat.calling.quality.SubmitCallQualitySurveyRequest;
import org.signal.chat.calling.quality.SubmitCallQualitySurveyResponse;
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
import org.whispersystems.textsecuregcm.limits.RateLimiters;
import org.whispersystems.textsecuregcm.metrics.CallQualityInvalidArgumentsException;
import org.whispersystems.textsecuregcm.metrics.CallQualitySurveyManager;
public class CallQualitySurveyGrpcService extends SimpleCallQualityGrpc.CallQualityImplBase {
@@ -38,8 +39,10 @@ public class CallQualitySurveyGrpcService extends SimpleCallQualityGrpc.CallQual
callQualitySurveyManager.submitCallQualitySurvey(request,
remoteAddress,
RequestAttributesUtil.getUserAgent().orElse(null));
} catch (final IllegalArgumentException e) {
throw Status.INVALID_ARGUMENT.withDescription(e.getMessage()).asRuntimeException();
} catch (final CallQualityInvalidArgumentsException e) {
throw e.getField()
.map(fieldName -> GrpcExceptions.fieldViolation(fieldName, e.getMessage()))
.orElseGet(() -> GrpcExceptions.invalidArguments(e.getMessage()));
}
return SubmitCallQualitySurveyResponse.getDefaultInstance();

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.textsecuregcm.metrics;
import javax.annotation.Nullable;
import java.util.Optional;
public class CallQualityInvalidArgumentsException extends Exception {
private final @Nullable String field;
public CallQualityInvalidArgumentsException(final String message) {
this(message, null);
}
public CallQualityInvalidArgumentsException(final String message, final String field) {
super(message);
this.field = field;
}
public Optional<String> getField() {
return Optional.ofNullable(field);
}
}

View File

@@ -49,7 +49,7 @@ public class CallQualitySurveyManager {
public void submitCallQualitySurvey(final SubmitCallQualitySurveyRequest submitCallQualitySurveyRequest,
final String remoteAddress,
final String userAgentString) {
final String userAgentString) throws CallQualityInvalidArgumentsException {
validateRequest(submitCallQualitySurveyRequest);
@@ -152,21 +152,21 @@ public class CallQualitySurveyManager {
}
@VisibleForTesting
static void validateRequest(final SubmitCallQualitySurveyRequest request) {
static void validateRequest(final SubmitCallQualitySurveyRequest request) throws CallQualityInvalidArgumentsException {
if (request.getStartTimestamp() == 0) {
throw new IllegalArgumentException("Start timestamp not specified");
throw new CallQualityInvalidArgumentsException("Start timestamp not specified", "startTimestamp");
}
if (request.getEndTimestamp() == 0) {
throw new IllegalArgumentException("End timestamp not specified");
throw new CallQualityInvalidArgumentsException("End timestamp not specified", "endTimestamp");
}
if (StringUtils.isBlank(request.getCallType())) {
throw new IllegalArgumentException("Call type not specified");
throw new CallQualityInvalidArgumentsException("Call type not specified", "callType");
}
if (StringUtils.isBlank(request.getCallEndReason())) {
throw new IllegalArgumentException("Call end reason not specified");
throw new CallQualityInvalidArgumentsException("Call end reason not specified", "callEndReason");
}
}
}