Skip to content

Commit 3abb74a

Browse files
committed
feat: add global policy for file rotation
1 parent 1631230 commit 3abb74a

File tree

7 files changed

+52
-5
lines changed

7 files changed

+52
-5
lines changed

src/main/java/com/gotocompany/firehose/config/BlobSinkConfig.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ public interface BlobSinkConfig extends AppConfig {
5050
@Key("SINK_BLOB_FILE_PARTITION_PROTO_TIMESTAMP_FIELD_NAME")
5151
String getFilePartitionProtoTimestampFieldName();
5252

53+
@Key("SINK_BLOB_GLOBAL_FILE_ROTATION_MAX_SIZE_BYTES")
54+
@DefaultValue("268435456")
55+
long getGlobalFileRotationMaxSizeBytes();
56+
57+
5358
@Key("SINK_BLOB_FILE_PARTITION_TIME_TYPE")
5459
@DefaultValue("EVENT_TIMESTAMP")
5560
TimePartitionType getFilePartitionTimeType();

src/main/java/com/gotocompany/firehose/sink/blob/BlobSinkFactory.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.gotocompany.firehose.sink.blob.message.MessageDeSerializer;
88
import com.gotocompany.firehose.sink.blob.writer.WriterOrchestrator;
99
import com.gotocompany.firehose.sink.blob.writer.local.LocalStorage;
10+
import com.gotocompany.firehose.sink.blob.writer.local.policy.GlobalWriterPolicy;
1011
import com.gotocompany.firehose.sink.blob.writer.local.policy.SizeBasedRotatingPolicy;
1112
import com.gotocompany.firehose.sink.blob.writer.local.policy.TimeBasedRotatingPolicy;
1213
import com.gotocompany.firehose.sink.blob.writer.local.policy.WriterPolicy;
@@ -53,13 +54,16 @@ private static LocalStorage getLocalFileWriterWrapper(BlobSinkConfig sinkConfig,
5354
Descriptors.Descriptor outputMessageDescriptor = stencilClient.get(sinkConfig.getInputSchemaProtoClass());
5455
Descriptors.Descriptor metadataMessageDescriptor = getMetadataMessageDescriptor(sinkConfig);
5556
List<WriterPolicy> writerPolicies = new ArrayList<>();
57+
List<GlobalWriterPolicy> globalWriterPolicies = new ArrayList<>();
5658
writerPolicies.add(new TimeBasedRotatingPolicy(sinkConfig.getLocalFileRotationDurationMS()));
5759
writerPolicies.add(new SizeBasedRotatingPolicy(sinkConfig.getLocalFileRotationMaxSizeBytes()));
60+
globalWriterPolicies.add(new SizeBasedRotatingPolicy(sinkConfig.getGlobalFileRotationMaxSizeBytes()));
5861
return new LocalStorage(
5962
sinkConfig,
6063
outputMessageDescriptor,
6164
metadataMessageDescriptor.getFields(),
6265
writerPolicies,
66+
globalWriterPolicies,
6367
new FirehoseInstrumentation(statsDReporter, LocalStorage.class));
6468
}
6569

src/main/java/com/gotocompany/firehose/sink/blob/writer/local/LocalFileChecker.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,16 @@ public LocalFileChecker(Queue<LocalFileMetadata> toBeFlushedToRemotePaths,
3131
@Override
3232
public void run() {
3333
firehoseInstrumentation.captureValue(BlobStorageMetrics.LOCAL_FILE_OPEN_TOTAL, timePartitionWriterMap.size());
34-
Map<Path, LocalFileWriter> toBeRotated =
35-
timePartitionWriterMap.entrySet().stream().filter(kv -> localStorage.shouldRotate(kv.getValue()))
36-
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
34+
Map<Path, LocalFileWriter> toBeRotated;
35+
if (localStorage.shouldRotate(timePartitionWriterMap.values())) {
36+
// rotate all
37+
toBeRotated = timePartitionWriterMap.entrySet().stream()
38+
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
39+
} else {
40+
toBeRotated =
41+
timePartitionWriterMap.entrySet().stream().filter(kv -> localStorage.shouldRotate(kv.getValue()))
42+
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
43+
}
3744
timePartitionWriterMap.entrySet().removeAll(toBeRotated.entrySet());
3845
toBeRotated.forEach((path, writer) -> {
3946
try {

src/main/java/com/gotocompany/firehose/sink/blob/writer/local/LocalStorage.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44
import com.gotocompany.firehose.config.BlobSinkConfig;
55
import com.gotocompany.firehose.exception.ConfigurationException;
66
import com.gotocompany.firehose.metrics.FirehoseInstrumentation;
7+
import com.gotocompany.firehose.sink.blob.writer.local.policy.GlobalWriterPolicy;
78
import com.gotocompany.firehose.sink.blob.writer.local.policy.WriterPolicy;
89
import lombok.AllArgsConstructor;
910

1011
import java.io.IOException;
1112
import java.nio.file.Files;
1213
import java.nio.file.Path;
1314
import java.nio.file.Paths;
15+
import java.util.Collection;
1416
import java.util.List;
17+
import java.util.Set;
1518
import java.util.UUID;
19+
import java.util.stream.Collectors;
1620

1721
@AllArgsConstructor
1822
public class LocalStorage {
@@ -21,6 +25,7 @@ public class LocalStorage {
2125
private final Descriptors.Descriptor messageDescriptor;
2226
private final List<Descriptors.FieldDescriptor> metadataFieldDescriptor;
2327
private final List<WriterPolicy> policies;
28+
private final List<GlobalWriterPolicy> globalPolicies;
2429
private final FirehoseInstrumentation firehoseInstrumentation;
2530

2631
public LocalFileWriter createLocalFileWriter(Path partitionPath) {
@@ -78,4 +83,10 @@ public void deleteLocalFile(Path... paths) throws IOException {
7883
public Boolean shouldRotate(LocalFileWriter writer) {
7984
return policies.stream().anyMatch(writerPolicy -> writerPolicy.shouldRotate(writer.getMetadata()));
8085
}
86+
87+
public Boolean shouldRotate(Collection<LocalFileWriter> writers) {
88+
return globalPolicies.stream().anyMatch(policy -> policy.shouldRotate(
89+
writers.stream().map(LocalFileWriter::getMetadata).collect(Collectors.toList())
90+
));
91+
}
8192
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.gotocompany.firehose.sink.blob.writer.local.policy;
2+
3+
import com.gotocompany.firehose.sink.blob.writer.local.LocalFileMetadata;
4+
5+
import java.util.List;
6+
7+
public interface GlobalWriterPolicy {
8+
9+
boolean shouldRotate(List<LocalFileMetadata> metadata);
10+
}

src/main/java/com/gotocompany/firehose/sink/blob/writer/local/policy/SizeBasedRotatingPolicy.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import com.gotocompany.firehose.sink.blob.writer.local.LocalFileMetadata;
44

5-
public class SizeBasedRotatingPolicy implements WriterPolicy {
5+
import java.util.List;
6+
7+
public class SizeBasedRotatingPolicy implements WriterPolicy, GlobalWriterPolicy {
68

79
private final long maxSize;
810

@@ -17,4 +19,10 @@ public SizeBasedRotatingPolicy(long maxSize) {
1719
public boolean shouldRotate(LocalFileMetadata metadata) {
1820
return metadata.getSize() >= maxSize;
1921
}
22+
23+
@Override
24+
public boolean shouldRotate(List<LocalFileMetadata> metadataList) {
25+
long totalSize = metadataList.stream().map(LocalFileMetadata::getSize).reduce(0L, Long::sum);
26+
return totalSize >= maxSize;
27+
}
2028
}

src/test/java/com/gotocompany/firehose/sink/blob/writer/local/LocalStorageTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.gotocompany.firehose.config.BlobSinkConfig;
66
import com.gotocompany.firehose.metrics.FirehoseInstrumentation;
77
import com.gotocompany.firehose.sink.blob.Constants;
8+
import com.gotocompany.firehose.sink.blob.writer.local.policy.GlobalWriterPolicy;
89
import com.gotocompany.firehose.sink.blob.writer.local.policy.WriterPolicy;
910
import org.junit.Test;
1011
import org.mockito.Mockito;
@@ -20,8 +21,9 @@ public void shouldDeleteFiles() throws Exception {
2021
BlobSinkConfig sinkConfig = Mockito.mock(BlobSinkConfig.class);
2122
List<Descriptors.FieldDescriptor> metadataFieldDescriptor = new ArrayList<>();
2223
List<WriterPolicy> policies = new ArrayList<>();
24+
List<GlobalWriterPolicy> globalWriterPolicies = new ArrayList<>();
2325
FirehoseInstrumentation firehoseInstrumentation = Mockito.mock(FirehoseInstrumentation.class);
24-
LocalStorage storage = new LocalStorage(sinkConfig, null, metadataFieldDescriptor, policies, firehoseInstrumentation);
26+
LocalStorage storage = new LocalStorage(sinkConfig, null, metadataFieldDescriptor, policies, globalWriterPolicies, firehoseInstrumentation);
2527
LocalStorage spy = Mockito.spy(storage);
2628
Mockito.doNothing().when(spy).deleteLocalFile(Paths.get("/tmp/a"), Paths.get("/tmp/.a.crc"));
2729
Mockito.when(sinkConfig.getLocalFileWriterType()).thenReturn(Constants.WriterType.PARQUET);

0 commit comments

Comments
 (0)