mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-19 23:18:05 +01:00
Allow optional size parameter when requesting message backup upload forms
This commit is contained in:
committed by
ravi-signal
parent
ae2d98750c
commit
3f62677176
@@ -8,6 +8,7 @@ package org.whispersystems.textsecuregcm.backup;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.dropwizard.util.DataSize;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.StatusRuntimeException;
|
||||
import io.micrometer.core.instrument.DistributionSummary;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
@@ -54,6 +55,7 @@ public class BackupManager {
|
||||
|
||||
static final String MESSAGE_BACKUP_NAME = "messageBackup";
|
||||
public static final long MAX_TOTAL_BACKUP_MEDIA_BYTES = DataSize.gibibytes(100).toBytes();
|
||||
public static final long MAX_MESSAGE_BACKUP_OBJECT_SIZE = DataSize.mebibytes(101).toBytes();
|
||||
public static final long MAX_MEDIA_OBJECT_SIZE = DataSize.mebibytes(101).toBytes();
|
||||
|
||||
// If the last media usage recalculation is over MAX_QUOTA_STALENESS, force a recalculation before quota enforcement.
|
||||
|
||||
@@ -516,12 +516,24 @@ public class ArchiveController {
|
||||
|
||||
@Parameter(description = BackupAuthCredentialPresentationSignature.DESCRIPTION, schema = @Schema(implementation = String.class))
|
||||
@NotNull
|
||||
@HeaderParam(X_SIGNAL_ZK_AUTH_SIGNATURE) final BackupAuthCredentialPresentationSignature signature) {
|
||||
@HeaderParam(X_SIGNAL_ZK_AUTH_SIGNATURE) final BackupAuthCredentialPresentationSignature signature,
|
||||
|
||||
@Parameter(description = "The size of the message backup to upload in bytes")
|
||||
@QueryParam("uploadLength") final Optional<Long> uploadLength) {
|
||||
if (account.isPresent()) {
|
||||
throw new BadRequestException("must not use authenticated connection for anonymous operations");
|
||||
}
|
||||
return backupManager.authenticateBackupUser(presentation.presentation, signature.signature, userAgent)
|
||||
.thenCompose(backupManager::createMessageBackupUploadDescriptor)
|
||||
.thenCompose(backupUser -> {
|
||||
final boolean oversize = uploadLength
|
||||
.map(length -> length > BackupManager.MAX_MESSAGE_BACKUP_OBJECT_SIZE)
|
||||
.orElse(false);
|
||||
backupMetrics.updateMessageBackupSizeDistribution(backupUser, oversize, uploadLength);
|
||||
if (oversize) {
|
||||
throw new ClientErrorException("exceeded maximum uploadLength", Response.Status.REQUEST_ENTITY_TOO_LARGE);
|
||||
}
|
||||
return backupManager.createMessageBackupUploadDescriptor(backupUser);
|
||||
})
|
||||
.thenApply(result -> new UploadDescriptorResponse(
|
||||
result.cdn(),
|
||||
result.key(),
|
||||
|
||||
@@ -101,7 +101,18 @@ public class BackupsAnonymousGrpcService extends ReactorBackupsAnonymousGrpc.Bac
|
||||
public Mono<GetUploadFormResponse> getUploadForm(final GetUploadFormRequest request) {
|
||||
return authenticateBackupUserMono(request.getSignedPresentation())
|
||||
.flatMap(backupUser -> switch (request.getUploadTypeCase()) {
|
||||
case MESSAGES -> Mono.fromFuture(backupManager.createMessageBackupUploadDescriptor(backupUser));
|
||||
case MESSAGES -> {
|
||||
final long uploadLength = request.getMessages().getUploadLength();
|
||||
final boolean oversize = uploadLength > BackupManager.MAX_MESSAGE_BACKUP_OBJECT_SIZE;
|
||||
backupMetrics.updateMessageBackupSizeDistribution(backupUser, oversize, Optional.of(uploadLength));
|
||||
if (oversize) {
|
||||
yield Mono.error(Status.FAILED_PRECONDITION
|
||||
.withDescription("Exceeds max upload length")
|
||||
.asRuntimeException());
|
||||
}
|
||||
|
||||
yield Mono.fromFuture(backupManager.createMessageBackupUploadDescriptor(backupUser));
|
||||
}
|
||||
case MEDIA -> Mono.fromCompletionStage(backupManager.createTemporaryAttachmentUploadDescriptor(backupUser));
|
||||
case UPLOADTYPE_NOT_SET -> Mono.error(Status.INVALID_ARGUMENT
|
||||
.withDescription("Must set upload_type")
|
||||
|
||||
@@ -8,17 +8,21 @@ package org.whispersystems.textsecuregcm.metrics;
|
||||
import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.micrometer.core.instrument.DistributionSummary;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import org.signal.libsignal.zkgroup.backups.BackupCredentialType;
|
||||
import org.whispersystems.textsecuregcm.auth.AuthenticatedBackupUser;
|
||||
import org.whispersystems.textsecuregcm.backup.CopyResult;
|
||||
import java.util.Optional;
|
||||
|
||||
public class BackupMetrics {
|
||||
|
||||
private final static String COPY_MEDIA_COUNTER_NAME = name(BackupMetrics.class, "copyMedia");
|
||||
private final static String GET_BACKUP_CREDENTIALS_NAME = name(BackupMetrics.class, "getBackupCredentials");
|
||||
private final static String MESSAGE_BACKUP_SIZE_NAME = name(BackupMetrics.class, "messageBackupSize");
|
||||
|
||||
|
||||
private MeterRegistry registry;
|
||||
@@ -48,4 +52,19 @@ public class BackupMetrics {
|
||||
.increment();
|
||||
}
|
||||
|
||||
public void updateMessageBackupSizeDistribution(
|
||||
AuthenticatedBackupUser authenticatedBackupUser,
|
||||
final boolean oversize,
|
||||
final Optional<Long> backupLength) {
|
||||
DistributionSummary.builder(MESSAGE_BACKUP_SIZE_NAME)
|
||||
.publishPercentileHistogram(true)
|
||||
.tags(Tags.of(
|
||||
UserAgentTagUtil.getPlatformTag(authenticatedBackupUser.userAgent()),
|
||||
Tag.of("tier", authenticatedBackupUser.backupLevel().name().toLowerCase()),
|
||||
Tag.of("oversize", Boolean.toString(oversize)),
|
||||
Tag.of("hasBackupLength", Boolean.toString(backupLength.isPresent()))))
|
||||
.register(Metrics.globalRegistry)
|
||||
.record(backupLength.orElse(0L));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user