Skip to content

Commit 407d9d0

Browse files
committed
rename ExternalStorage to ExternalStorageOptions.
1 parent f434a51 commit 407d9d0

6 files changed

Lines changed: 245 additions & 19 deletions

File tree

temporal-sdk/src/main/java/io/temporal/payload/storage/ExternalStorage.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
/** Configuration for offloading large payloads to external storage. */
1515
@Experimental
16-
public final class ExternalStorage {
16+
public final class ExternalStorageOptions {
1717
static final int DEFAULT_PAYLOAD_SIZE_THRESHOLD = 256 * 1024;
1818

1919
public static Builder newBuilder() {
@@ -24,7 +24,7 @@ public static Builder newBuilder() {
2424
private final @Nonnull StorageDriverSelector driverSelector;
2525
private final int payloadSizeThreshold;
2626

27-
private ExternalStorage(
27+
private ExternalStorageOptions(
2828
@Nonnull List<StorageDriver> drivers,
2929
@Nonnull StorageDriverSelector driverSelector,
3030
int payloadSizeThreshold) {
@@ -54,7 +54,7 @@ public int getPayloadSizeThreshold() {
5454
public static final class Builder {
5555
private List<StorageDriver> drivers = Collections.emptyList();
5656
private StorageDriverSelector driverSelector;
57-
private int payloadSizeThreshold = ExternalStorage.DEFAULT_PAYLOAD_SIZE_THRESHOLD;
57+
private int payloadSizeThreshold = ExternalStorageOptions.DEFAULT_PAYLOAD_SIZE_THRESHOLD;
5858

5959
private Builder() {}
6060

@@ -84,7 +84,7 @@ public Builder setPayloadSizeThreshold(int payloadSizeThreshold) {
8484
return this;
8585
}
8686

87-
public ExternalStorage build() {
87+
public ExternalStorageOptions build() {
8888
Preconditions.checkState(!drivers.isEmpty(), "At least one driver must be provided");
8989
Preconditions.checkState(
9090
payloadSizeThreshold >= 0, "payloadSizeThreshold must be greater than or equal to zero");
@@ -102,7 +102,7 @@ public ExternalStorage build() {
102102
StorageDriver driver = drivers.get(0);
103103
selector = (context, payload) -> driver;
104104
}
105-
return new ExternalStorage(drivers, selector, payloadSizeThreshold);
105+
return new ExternalStorageOptions(drivers, selector, payloadSizeThreshold);
106106
}
107107
}
108108
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package io.temporal.payload.storage;
2+
3+
import com.google.common.base.Preconditions;
4+
import io.temporal.common.Experimental;
5+
import java.util.ArrayList;
6+
import java.util.Collections;
7+
import java.util.HashSet;
8+
import java.util.List;
9+
import java.util.Objects;
10+
import java.util.Set;
11+
import javax.annotation.Nonnull;
12+
import javax.annotation.Nullable;
13+
14+
/** Configuration for offloading large payloads to external storage. */
15+
@Experimental
16+
public final class ExternalStorageOptions {
17+
static final int DEFAULT_PAYLOAD_SIZE_THRESHOLD = 256 * 1024;
18+
19+
public static Builder newBuilder() {
20+
return new Builder();
21+
}
22+
23+
private final @Nonnull List<StorageDriver> drivers;
24+
private final @Nonnull StorageDriverSelector driverSelector;
25+
private final int payloadSizeThreshold;
26+
27+
private ExternalStorageOptions(
28+
@Nonnull List<StorageDriver> drivers,
29+
@Nonnull StorageDriverSelector driverSelector,
30+
int payloadSizeThreshold) {
31+
this.drivers = Collections.unmodifiableList(new ArrayList<>(drivers));
32+
this.driverSelector = driverSelector;
33+
this.payloadSizeThreshold = payloadSizeThreshold;
34+
}
35+
36+
@Nonnull
37+
public List<StorageDriver> getDrivers() {
38+
return drivers;
39+
}
40+
41+
@Nonnull
42+
public StorageDriverSelector getDriverSelector() {
43+
return driverSelector;
44+
}
45+
46+
/**
47+
* Minimum payload size in bytes before external storage is considered. {@code 0} stores all
48+
* payloads. Defaults to 256 KiB.
49+
*/
50+
public int getPayloadSizeThreshold() {
51+
return payloadSizeThreshold;
52+
}
53+
54+
public static final class Builder {
55+
private List<StorageDriver> drivers = Collections.emptyList();
56+
private StorageDriverSelector driverSelector;
57+
private int payloadSizeThreshold = ExternalStorageOptions.DEFAULT_PAYLOAD_SIZE_THRESHOLD;
58+
59+
private Builder() {}
60+
61+
/**
62+
* At least one driver is required. When more than one is set, a selector is also required. If
63+
* this is called multiple times, the last one wins and previous drivers are overwritten.
64+
*/
65+
public Builder setDrivers(@Nonnull List<StorageDriver> drivers) {
66+
this.drivers = Objects.requireNonNull(drivers, "drivers");
67+
return this;
68+
}
69+
70+
/** Convenience for registering a single driver; no selector is needed in this case. */
71+
public Builder setDriver(@Nonnull StorageDriver driver) {
72+
return setDrivers(Collections.singletonList(Objects.requireNonNull(driver, "driver")));
73+
}
74+
75+
/** Required when more than one driver is registered; with a single driver it is optional. */
76+
public Builder setDriverSelector(@Nullable StorageDriverSelector driverSelector) {
77+
this.driverSelector = driverSelector;
78+
return this;
79+
}
80+
81+
/** Set to {@code 0} to store all payloads. Defaults to 256 KiB. */
82+
public Builder setPayloadSizeThreshold(int payloadSizeThreshold) {
83+
this.payloadSizeThreshold = payloadSizeThreshold;
84+
return this;
85+
}
86+
87+
public ExternalStorageOptions build() {
88+
Preconditions.checkState(!drivers.isEmpty(), "At least one driver must be provided");
89+
Preconditions.checkState(
90+
payloadSizeThreshold >= 0, "payloadSizeThreshold must be greater than or equal to zero");
91+
Set<String> names = new HashSet<>();
92+
for (StorageDriver driver : drivers) {
93+
String name = driver.getName();
94+
Preconditions.checkState(
95+
names.add(name), "Multiple drivers registered with name '%s'", name);
96+
}
97+
Preconditions.checkState(
98+
drivers.size() == 1 || driverSelector != null,
99+
"driverSelector must be specified when more than one driver is registered");
100+
StorageDriverSelector selector = driverSelector;
101+
if (selector == null) {
102+
StorageDriver driver = drivers.get(0);
103+
selector = (context, payload) -> driver;
104+
}
105+
return new ExternalStorageOptions(drivers, selector, payloadSizeThreshold);
106+
}
107+
}
108+
}

temporal-sdk/src/main/java/io/temporal/payload/storage/StorageDriver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
public interface StorageDriver {
1212
/**
1313
* Name of this driver instance, unique among the drivers registered in a single {@link
14-
* ExternalStorage}. Used as the routing key recorded in a stored payload's reference and resolved
14+
* ExternalStorageOptions}. Used as the routing key recorded in a stored payload's reference and resolved
1515
* back to this driver on retrieval.
1616
*/
1717
@Nonnull

temporal-sdk/src/main/java/io/temporal/payload/storage/StorageDriverSelector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
public interface StorageDriverSelector {
1212
/**
1313
* Returns the driver to store {@code payload}, which must be one of the drivers registered in the
14-
* {@link ExternalStorage}, or {@code null} to leave the payload stored inline.
14+
* {@link ExternalStorageOptions}, or {@code null} to leave the payload stored inline.
1515
*/
1616
@Nullable
1717
StorageDriver selectDriver(@Nonnull StorageDriverStoreContext context, @Nonnull Payload payload);
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package io.temporal.payload.storage;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNotNull;
5+
import static org.junit.Assert.assertSame;
6+
7+
import io.temporal.api.common.v1.Payload;
8+
import java.util.Arrays;
9+
import java.util.Collections;
10+
import java.util.List;
11+
import java.util.concurrent.CompletableFuture;
12+
import org.junit.Test;
13+
14+
public class ExternalStorageOptionsTest {
15+
16+
private static StorageDriverStoreContext storeContext(StorageDriverTargetInfo target) {
17+
return new StorageDriverStoreContext() {
18+
@Override
19+
public StorageDriverTargetInfo getTarget() {
20+
return target;
21+
}
22+
};
23+
}
24+
25+
private static StorageDriver driver(String name) {
26+
return new StorageDriver() {
27+
@Override
28+
public String getName() {
29+
return name;
30+
}
31+
32+
@Override
33+
public String getType() {
34+
return "test";
35+
}
36+
37+
@Override
38+
public CompletableFuture<List<StorageDriverClaim>> store(
39+
StorageDriverStoreContext context, List<Payload> payloads) {
40+
throw new UnsupportedOperationException();
41+
}
42+
43+
@Override
44+
public CompletableFuture<List<Payload>> retrieve(
45+
StorageDriverRetrieveContext context, List<StorageDriverClaim> claims) {
46+
throw new UnsupportedOperationException();
47+
}
48+
};
49+
}
50+
51+
@Test
52+
public void singleDriverNoSelectorSynthesizesSelector() {
53+
StorageDriver a = driver("a");
54+
ExternalStorageOptions storage = ExternalStorageOptions.newBuilder().setDriver(a).build();
55+
assertEquals(1, storage.getDrivers().size());
56+
StorageDriverSelector selector = storage.getDriverSelector();
57+
assertNotNull(selector);
58+
assertSame(a, selector.selectDriver(storeContext(null), Payload.getDefaultInstance()));
59+
}
60+
61+
@Test
62+
public void multipleDriversWithSelectorIsValid() {
63+
StorageDriver a = driver("a");
64+
ExternalStorageOptions storage =
65+
ExternalStorageOptions.newBuilder()
66+
.setDrivers(Arrays.asList(a, driver("b")))
67+
.setDriverSelector((context, payload) -> a)
68+
.build();
69+
assertEquals(2, storage.getDrivers().size());
70+
assertNotNull(storage.getDriverSelector());
71+
}
72+
73+
@Test
74+
public void lastSetDriversWins() {
75+
StorageDriver a = driver("a");
76+
StorageDriver b = driver("b");
77+
StorageDriver c = driver("c");
78+
ExternalStorageOptions storage =
79+
ExternalStorageOptions.newBuilder()
80+
.setDrivers(Arrays.asList(a, b))
81+
.setDrivers(Collections.singletonList(c))
82+
.build();
83+
assertEquals(Collections.singletonList(c), storage.getDrivers());
84+
}
85+
86+
@Test
87+
public void zeroThresholdStoresAll() {
88+
ExternalStorageOptions storage =
89+
ExternalStorageOptions.newBuilder()
90+
.setDrivers(Collections.singletonList(driver("a")))
91+
.setPayloadSizeThreshold(0)
92+
.build();
93+
assertEquals(0, storage.getPayloadSizeThreshold());
94+
}
95+
96+
@Test(expected = IllegalStateException.class)
97+
public void noDriversRejected() {
98+
ExternalStorageOptions.newBuilder().build();
99+
}
100+
101+
@Test(expected = IllegalStateException.class)
102+
public void duplicateDriverNamesRejected() {
103+
ExternalStorageOptions.newBuilder().setDrivers(Arrays.asList(driver("dup"), driver("dup"))).build();
104+
}
105+
106+
@Test(expected = IllegalStateException.class)
107+
public void multipleDriversRequireSelector() {
108+
ExternalStorageOptions.newBuilder().setDrivers(Arrays.asList(driver("a"), driver("b"))).build();
109+
}
110+
111+
@Test(expected = IllegalStateException.class)
112+
public void negativeThresholdRejected() {
113+
ExternalStorageOptions.newBuilder()
114+
.setDrivers(Collections.singletonList(driver("a")))
115+
.setPayloadSizeThreshold(-1)
116+
.build();
117+
}
118+
}

temporal-sdk/src/test/java/io/temporal/payload/storage/ExternalStorageTest.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import java.util.concurrent.CompletableFuture;
1212
import org.junit.Test;
1313

14-
public class ExternalStorageTest {
14+
public class ExternalStorageOptionsTest {
1515

1616
private static StorageDriverStoreContext storeContext(StorageDriverTargetInfo target) {
1717
return new StorageDriverStoreContext() {
@@ -51,7 +51,7 @@ public CompletableFuture<List<Payload>> retrieve(
5151
@Test
5252
public void singleDriverNoSelectorSynthesizesSelector() {
5353
StorageDriver a = driver("a");
54-
ExternalStorage storage = ExternalStorage.newBuilder().setDriver(a).build();
54+
ExternalStorageOptions storage = ExternalStorageOptions.newBuilder().setDriver(a).build();
5555
assertEquals(1, storage.getDrivers().size());
5656
StorageDriverSelector selector = storage.getDriverSelector();
5757
assertNotNull(selector);
@@ -61,8 +61,8 @@ public void singleDriverNoSelectorSynthesizesSelector() {
6161
@Test
6262
public void multipleDriversWithSelectorIsValid() {
6363
StorageDriver a = driver("a");
64-
ExternalStorage storage =
65-
ExternalStorage.newBuilder()
64+
ExternalStorageOptions storage =
65+
ExternalStorageOptions.newBuilder()
6666
.setDrivers(Arrays.asList(a, driver("b")))
6767
.setDriverSelector((context, payload) -> a)
6868
.build();
@@ -75,8 +75,8 @@ public void lastSetDriversWins() {
7575
StorageDriver a = driver("a");
7676
StorageDriver b = driver("b");
7777
StorageDriver c = driver("c");
78-
ExternalStorage storage =
79-
ExternalStorage.newBuilder()
78+
ExternalStorageOptions storage =
79+
ExternalStorageOptions.newBuilder()
8080
.setDrivers(Arrays.asList(a, b))
8181
.setDrivers(Collections.singletonList(c))
8282
.build();
@@ -85,8 +85,8 @@ public void lastSetDriversWins() {
8585

8686
@Test
8787
public void zeroThresholdStoresAll() {
88-
ExternalStorage storage =
89-
ExternalStorage.newBuilder()
88+
ExternalStorageOptions storage =
89+
ExternalStorageOptions.newBuilder()
9090
.setDrivers(Collections.singletonList(driver("a")))
9191
.setPayloadSizeThreshold(0)
9292
.build();
@@ -95,22 +95,22 @@ public void zeroThresholdStoresAll() {
9595

9696
@Test(expected = IllegalStateException.class)
9797
public void noDriversRejected() {
98-
ExternalStorage.newBuilder().build();
98+
ExternalStorageOptions.newBuilder().build();
9999
}
100100

101101
@Test(expected = IllegalStateException.class)
102102
public void duplicateDriverNamesRejected() {
103-
ExternalStorage.newBuilder().setDrivers(Arrays.asList(driver("dup"), driver("dup"))).build();
103+
ExternalStorageOptions.newBuilder().setDrivers(Arrays.asList(driver("dup"), driver("dup"))).build();
104104
}
105105

106106
@Test(expected = IllegalStateException.class)
107107
public void multipleDriversRequireSelector() {
108-
ExternalStorage.newBuilder().setDrivers(Arrays.asList(driver("a"), driver("b"))).build();
108+
ExternalStorageOptions.newBuilder().setDrivers(Arrays.asList(driver("a"), driver("b"))).build();
109109
}
110110

111111
@Test(expected = IllegalStateException.class)
112112
public void negativeThresholdRejected() {
113-
ExternalStorage.newBuilder()
113+
ExternalStorageOptions.newBuilder()
114114
.setDrivers(Collections.singletonList(driver("a")))
115115
.setPayloadSizeThreshold(-1)
116116
.build();

0 commit comments

Comments
 (0)