Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade test #167

Merged
merged 7 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config/allowed-licenses.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
},
{
"moduleName": "org.jetbrains.kotlinx:kotlinx-serialization-core"
},
{
"moduleName": "com.squareup.okio:okio"
}
]
}
4 changes: 4 additions & 0 deletions config/license-normalizer-bundle.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
{
"bundleName": "Apache-2.0",
"modulePattern": "org.jetbrains.kotlinx:kotlinx-serialization-core:.*"
},
{
"bundleName": "Apache-2.0",
"modulePattern": "com.squareup.okio:okio:.*"
}
]
}
1 change: 1 addition & 0 deletions contracts/src/main/proto/list.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ service ListService {

rpc Append(AppendRequest) returns (google.protobuf.Empty);
rpc Clear(Request) returns (List);
rpc Get(Request) returns (List);
}

message AppendRequest {
Expand Down
34 changes: 34 additions & 0 deletions contracts/src/main/proto/upgrade_test.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
syntax = "proto3";

option java_package = "dev.restate.e2e.services.upgradetest";
option java_outer_classname = "UpgradeTestProto";

import "google/protobuf/empty.proto";
import "dev/restate/ext.proto";
import "dev/restate/core.proto";

package upgrade_test;

service UpgradeTestService {
option (dev.restate.ext.service_type) = UNKEYED;

rpc ExecuteSimple(google.protobuf.Empty) returns (Result);
rpc ExecuteComplex(google.protobuf.Empty) returns (Result);
}

service AwakeableHolderService {
option (dev.restate.ext.service_type) = SINGLETON;

rpc Hold(dev.restate.core.AwakeableIdentifier) returns (google.protobuf.Empty);
rpc HasAwakeable(google.protobuf.Empty) returns (HasAwakeableResponse);
rpc Unlock(google.protobuf.Empty) returns (google.protobuf.Empty);
}

message Result {
string message = 1;
}

message HasAwakeableResponse {
bool has_awakeable = 1;
}

2 changes: 1 addition & 1 deletion docs/dev/verification.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ SERVICES=verifier.CommandVerifier,interpreter.CommandInterpreter npm run app

Then discover the services:
```bash
$ curl 127.0.0.1:8081/endpoint/discover -H 'content-type: application/json' -d '{"uri": "http://localhost:8080"}'
$ curl 127.0.0.1:8081/endpoints -H 'content-type: application/json' -d '{"uri": "http://localhost:8080"}'
{"services":["verifier.CommandVerifier","interpreter.CommandInterpreter"]}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
import dev.restate.e2e.services.sideeffect.SideEffectGrpc;
import dev.restate.e2e.services.sideeffect.SideEffectService;
import dev.restate.e2e.services.singletoncounter.SingletonCounterGrpc;
import dev.restate.e2e.services.upgradetest.AwakeableHolderService;
import dev.restate.e2e.services.upgradetest.AwakeableHolderServiceGrpc;
import dev.restate.e2e.services.upgradetest.UpgradeTestService;
import dev.restate.e2e.services.upgradetest.UpgradeTestServiceGrpc;
import dev.restate.sdk.vertx.RestateHttpEndpointBuilder;
import io.vertx.core.Vertx;
import java.util.Objects;
Expand Down Expand Up @@ -69,6 +73,12 @@ public static void main(String[] args) {
case SideEffectGrpc.SERVICE_NAME:
restateHttpEndpointBuilder.withService(new SideEffectService());
break;
case AwakeableHolderServiceGrpc.SERVICE_NAME:
restateHttpEndpointBuilder.withService(new AwakeableHolderService());
break;
case UpgradeTestServiceGrpc.SERVICE_NAME:
restateHttpEndpointBuilder.withService(new UpgradeTestService());
break;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,13 @@ public void clear(ListProto.Request request, StreamObserver<ListProto.List> resp
responseObserver.onNext(list);
responseObserver.onCompleted();
}

@Override
public void get(ListProto.Request request, StreamObserver<ListProto.List> responseObserver) {
ListProto.List list =
restateContext().get(LIST_KEY).orElse(ListProto.List.getDefaultInstance());

responseObserver.onNext(list);
responseObserver.onCompleted();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package dev.restate.e2e.services.upgradetest;

import com.google.protobuf.Empty;
import dev.restate.e2e.services.upgradetest.UpgradeTestProto.HasAwakeableResponse;
import dev.restate.generated.core.AwakeableIdentifier;
import dev.restate.sdk.blocking.RestateBlockingService;
import dev.restate.sdk.blocking.RestateContext;
import dev.restate.sdk.core.StateKey;
import dev.restate.sdk.core.TypeTag;
import io.grpc.stub.StreamObserver;

public class AwakeableHolderService
extends AwakeableHolderServiceGrpc.AwakeableHolderServiceImplBase
implements RestateBlockingService {

private final StateKey<AwakeableIdentifier> STATE_ID =
StateKey.of("identifier", AwakeableIdentifier.class);

@Override
public void hold(AwakeableIdentifier request, StreamObserver<Empty> responseObserver) {
restateContext().set(STATE_ID, request);

responseObserver.onNext(Empty.getDefaultInstance());
responseObserver.onCompleted();
}

@Override
public void hasAwakeable(Empty request, StreamObserver<HasAwakeableResponse> responseObserver) {
responseObserver.onNext(
HasAwakeableResponse.newBuilder()
.setHasAwakeable(restateContext().get(STATE_ID).isPresent())
.build());
responseObserver.onCompleted();
}

@Override
public void unlock(Empty request, StreamObserver<Empty> responseObserver) {
RestateContext ctx = restateContext();

ctx.awakeableHandle(ctx.get(STATE_ID).get()).complete(TypeTag.STRING_UTF8, "");

responseObserver.onNext(Empty.getDefaultInstance());
responseObserver.onCompleted();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package dev.restate.e2e.services.upgradetest;

import com.google.protobuf.Empty;
import dev.restate.e2e.services.collections.list.ListProto;
import dev.restate.e2e.services.collections.list.ListServiceGrpc;
import dev.restate.e2e.services.upgradetest.UpgradeTestProto.Result;
import dev.restate.sdk.blocking.Awakeable;
import dev.restate.sdk.blocking.RestateBlockingService;
import dev.restate.sdk.blocking.RestateContext;
import dev.restate.sdk.core.TypeTag;
import io.grpc.stub.StreamObserver;
import java.util.Objects;

public class UpgradeTestService extends UpgradeTestServiceGrpc.UpgradeTestServiceImplBase
implements RestateBlockingService {

// Value should be either "v1" or "v2"
private final String version =
Objects.requireNonNull(System.getenv("E2E_UPGRADETEST_VERSION")).trim();

@Override
public void executeSimple(Empty request, StreamObserver<Result> responseObserver) {
responseObserver.onNext(Result.newBuilder().setMessage(version).build());
responseObserver.onCompleted();
}

@Override
public void executeComplex(Empty request, StreamObserver<Result> responseObserver) {
RestateContext ctx = restateContext();

if (!"v1".equals(version)) {
throw new IllegalStateException(
"executeComplex should not be invoked with version different from 1!");
}

// In v1 case we create an awakeable, we ask the AwakeableHolderService to hold it, and then we
// await on it
Awakeable<String> awakeable = ctx.awakeable(TypeTag.STRING_UTF8);
ctx.backgroundCall(AwakeableHolderServiceGrpc.getHoldMethod(), awakeable.id());
awakeable.await();

// Store the result in List service, because this service is invoked with
// dev.restate.Ingress#Invoke
ctx.backgroundCall(
ListServiceGrpc.getAppendMethod(),
ListProto.AppendRequest.newBuilder().setListName("upgrade-test").setValue(version).build());

responseObserver.onNext(Result.newBuilder().setMessage(version).build());
responseObserver.onCompleted();
}
}
4 changes: 4 additions & 0 deletions services/node-services/src/collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,8 @@ export class ListService implements IListService {

return list;
}

get(): Promise<List> {
throw new Error("Method not implemented.");
}
}
2 changes: 2 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ dependencyResolutionManagement {
library("jackson-bom", "com.fasterxml.jackson", "jackson-bom").versionRef("jackson")
library("jackson-core", "com.fasterxml.jackson.core", "jackson-core").withoutVersion()
library("jackson-databind", "com.fasterxml.jackson.core", "jackson-databind").withoutVersion()
library("jackson-kotlin", "com.fasterxml.jackson.module", "jackson-module-kotlin")
.withoutVersion()

library("junit-all", "org.junit.jupiter", "junit-jupiter").versionRef("junit-jupiter")
library("junit-api", "org.junit.jupiter", "junit-jupiter-api").versionRef("junit-jupiter")
Expand Down
57 changes: 53 additions & 4 deletions test-utils/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,81 @@ plugins {
id("com.github.jk1.dependency-license-report") version "2.1"
}

// Dependency set for code-generating the openapi client
val fabrikt: Configuration by configurations.creating

dependencies {
fabrikt("com.cjbooms:fabrikt:9.0.1")

api(libs.junit.api)
api(libs.testcontainers.core)
api(libs.testcontainers.kafka)

api(libs.grpc.stub)

// Dependencies for the Meta client
api("com.squareup.okhttp3:okhttp:4.10.0")
api(platform(libs.jackson.bom))
api(libs.jackson.core)
api(libs.jackson.databind)
api(libs.jackson.kotlin)

// We need this to compile the code generated, can't remove these annotations from code gen :(
compileOnly("jakarta.validation:jakarta.validation-api:3.0.2")

implementation(libs.log4j.api)
implementation(libs.grpc.netty.shaded)
implementation(libs.grpc.protobuf)

implementation(libs.testcontainers.toxiproxy)

implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")

testImplementation(libs.junit.all)
testImplementation(libs.assertj)
}

val apiFile = "$projectDir/src/main/openapi/meta.json"
val generatedDir = "$buildDir/generated"

sourceSets { main { kotlin.srcDir("$generatedDir/src/main/kotlin") } }

java {
withJavadocJar()
withSourcesJar()
}

tasks {
val generateCode by
creating(JavaExec::class) {
inputs.files(apiFile)
outputs.dir(generatedDir)
outputs.cacheIf { true }
classpath(fabrikt)
mainClass.set("com.cjbooms.fabrikt.cli.CodeGen")
args =
listOf(
"--output-directory",
generatedDir,
"--base-package",
"dev.restate.e2e.utils.meta",
"--api-file",
apiFile,
"--validation-library",
"JAKARTA_VALIDATION",
"--targets",
"http_models",
"--targets",
"client",
)
}

// Make sure generateCode is correctly linked to compilation tasks
withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> { dependsOn(generateCode) }
withType<JavaCompile> { dependsOn(generateCode) }
withType<Jar> { dependsOn(generateCode) }

check { dependsOn(checkLicense) }
}

publishing {
repositories {
maven {
Expand All @@ -52,8 +103,6 @@ publishing {
}
}

tasks { check { dependsOn(checkLicense) } }

licenseReport {
renderers = arrayOf(com.github.jk1.license.render.CsvReportRenderer())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ abstract class BaseRestateDeployerExtension : ParameterResolver {
"http",
"127.0.0.1",
getDeployer(extensionContext).getContainerPort(RESTATE_RUNTIME, RUNTIME_META_ENDPOINT_PORT),
"/")
"")
}

private fun resolveContainerHandle(
Expand Down
Loading