use of io.pravega.controller.store.stream.records.StreamConfigurationRecord in project pravega by pravega.
the class ControllerMetadataJsonSerializerTest method testStreamConfigurationRecord.
@Test
public void testStreamConfigurationRecord() {
StreamConfiguration withScalingAndRetention = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(1)).retentionPolicy(RetentionPolicy.bySizeBytes(1L)).build();
StreamConfigurationRecord record1 = StreamConfigurationRecord.builder().streamConfiguration(withScalingAndRetention).streamName("a").scope("a").updating(true).build();
testRecordSerialization(record1, StreamConfigurationRecord.class);
StreamConfiguration withScalingOnly = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(1)).build();
StreamConfigurationRecord record2 = StreamConfigurationRecord.builder().streamConfiguration(withScalingOnly).streamName("a").scope("a").updating(true).build();
testRecordSerialization(record2, StreamConfigurationRecord.class);
StreamConfiguration withRetentionOnly = StreamConfiguration.builder().scalingPolicy(null).retentionPolicy(RetentionPolicy.bySizeBytes(1L)).build();
StreamConfigurationRecord record3 = StreamConfigurationRecord.builder().streamConfiguration(withRetentionOnly).streamName("a").scope("a").updating(true).build();
testRecordSerialization(record3, StreamConfigurationRecord.class);
}
use of io.pravega.controller.store.stream.records.StreamConfigurationRecord in project pravega by pravega.
the class StreamMetadataTasks method isUpdated.
@VisibleForTesting
CompletableFuture<Boolean> isUpdated(String scope, String stream, StreamConfiguration newConfig, OperationContext context) {
CompletableFuture<State> stateFuture = streamMetadataStore.getState(scope, stream, true, context, executor);
CompletableFuture<StreamConfigurationRecord> configPropertyFuture = streamMetadataStore.getConfigurationRecord(scope, stream, context, executor).thenApply(VersionedMetadata::getObject);
return CompletableFuture.allOf(stateFuture, configPropertyFuture).thenApply(v -> {
State state = stateFuture.join();
StreamConfigurationRecord configProperty = configPropertyFuture.join();
// if property is updating and doesn't match our request, it's a subsequent update
if (configProperty.isUpdating()) {
return !configProperty.getStreamConfiguration().equals(newConfig);
} else {
// if stream is sealed then update should not be allowed
if (state.equals(State.SEALED)) {
log.error("Cannot update a sealed stream {}/{}", scope, stream);
throw new UnsupportedOperationException("Cannot update a sealed stream: " + NameUtils.getScopedStreamName(scope, stream));
}
// and state is not updating
return !(configProperty.getStreamConfiguration().equals(newConfig) && state.equals(State.UPDATING));
}
});
}
use of io.pravega.controller.store.stream.records.StreamConfigurationRecord in project pravega by pravega.
the class PersistentStreamBase method completeUpdateConfiguration.
/**
* Update configuration at configurationPath.
*
* @return future of operation
*/
@Override
public CompletableFuture<Void> completeUpdateConfiguration(VersionedMetadata<StreamConfigurationRecord> existing, OperationContext context) {
StreamConfigurationRecord current = existing.getObject();
Preconditions.checkNotNull(current);
if (current.isUpdating()) {
StreamConfigurationRecord newProperty = StreamConfigurationRecord.complete(scope, name, current.getStreamConfiguration());
log.debug(context.getRequestId(), "Completing update configuration for stream {}/{}", scope, name);
return Futures.toVoid(setConfigurationData(new VersionedMetadata<>(newProperty, existing.getVersion()), context));
} else {
// idempotent
return CompletableFuture.completedFuture(null);
}
}
use of io.pravega.controller.store.stream.records.StreamConfigurationRecord in project pravega by pravega.
the class PersistentStreamBase method startUpdateConfiguration.
/**
* Update configuration at configurationPath.
*
* @param newConfiguration new stream configuration.
* @return future of operation.
*/
@Override
public CompletableFuture<Void> startUpdateConfiguration(final StreamConfiguration newConfiguration, OperationContext context) {
return getVersionedConfigurationRecord(context).thenCompose(configRecord -> {
Preconditions.checkArgument(!configRecord.getObject().isUpdating());
StreamConfiguration oldCfg = configRecord.getObject().getStreamConfiguration();
// Check for tags that needs to be removed.
Set<String> currentTags = new HashSet<>(oldCfg.getTags());
currentTags.removeAll(newConfiguration.getTags());
// Create a StreamConfigurationRecord with the newer Configuration.
StreamConfigurationRecord update;
if (StreamConfiguration.isTagOnlyChange(oldCfg, newConfiguration)) {
update = StreamConfigurationRecord.updateTag(scope, name, newConfiguration, currentTags);
} else {
update = StreamConfigurationRecord.update(scope, name, newConfiguration, currentTags);
}
// Update this in the metadata Stoe.
return Futures.toVoid(setConfigurationData(new VersionedMetadata<>(update, configRecord.getVersion()), context));
});
}
use of io.pravega.controller.store.stream.records.StreamConfigurationRecord in project pravega by pravega.
the class RequestHandlersTest method idempotentUpdateCompletedScale.
@Test(timeout = 300000)
public void idempotentUpdateCompletedScale() throws Exception {
String stream = "update3";
StreamMetadataStore streamStore1 = getStore();
StreamMetadataStore streamStore1Spied = spy(getStore());
StreamConfiguration config = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(1)).build();
streamStore1.createStream(scope, stream, config, System.currentTimeMillis(), null, executor).join();
streamStore1.setState(scope, stream, State.ACTIVE, null, executor).join();
StreamMetadataStore streamStore2 = getStore();
UpdateStreamTask requestHandler1 = new UpdateStreamTask(streamMetadataTasks, streamStore1Spied, bucketStore, executor);
UpdateStreamTask requestHandler2 = new UpdateStreamTask(streamMetadataTasks, streamStore2, bucketStore, executor);
CompletableFuture<Void> wait = new CompletableFuture<>();
CompletableFuture<Void> signal = new CompletableFuture<>();
config = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(2)).build();
streamStore1.startUpdateConfiguration(scope, stream, config, null, executor).join();
UpdateStreamEvent event = new UpdateStreamEvent(scope, stream, System.currentTimeMillis());
// make this wait at reset epoch transition. this has already changed the state to updating. both executions are
// performing the same update.
doAnswer(x -> {
signal.complete(null);
wait.join();
return streamStore1.completeScale(x.getArgument(0), x.getArgument(1), x.getArgument(2), x.getArgument(3), x.getArgument(4));
}).when(streamStore1Spied).completeScale(anyString(), anyString(), any(), any(), any());
CompletableFuture<Void> future1 = CompletableFuture.completedFuture(null).thenComposeAsync(v -> requestHandler1.execute(event), executor);
signal.join();
requestHandler2.execute(event).join();
wait.complete(null);
AssertExtensions.assertSuppliedFutureThrows("first update job should fail", () -> future1, e -> Exceptions.unwrap(e) instanceof StoreException.WriteConflictException);
VersionedMetadata<StreamConfigurationRecord> versioned = streamStore1.getConfigurationRecord(scope, stream, null, executor).join();
assertFalse(versioned.getObject().isUpdating());
assertEquals(2, getVersionNumber(versioned.getVersion()));
assertEquals(State.ACTIVE, streamStore1.getState(scope, stream, true, null, executor).join());
assertEquals(1, streamStore1.getActiveEpoch(scope, stream, null, true, executor).join().getEpoch());
// repeat the above experiment with complete scale step also having been performed.
streamStore1.close();
streamStore2.close();
}
Aggregations