Skip to content

Commit

Permalink
Enable existing service to be as TransientService (#3221)
Browse files Browse the repository at this point in the history
### Motivation

 - Provide a way to make existing services as `TransientService`
   - In some cases, users want to make a service not to collect metrics like a `GrpcService` which implements [GRPC Health Checking Protocol](https://github.com/grpc/grpc/blob/master/doc/health-checking.md)

### Modifications

 - Add `newDecorator` to `TransientHttpService` and `TransientRpcService`
 - Add `WrappingTransientHttpService` and `WrappingTransientRpcService` internally

### Result

 - Users can make existing service to be as `TransientService` by decorating with the `TransientHttpService` or `TransientRpcService` as follows:

   ```java
   builder.service("/docs", new DocService().decorate(
       TransientHttpService.newDecorator(TransientServiceOption.WITH_ACCESS_LOGGING)));
   ```
  • Loading branch information
0x1306e6d authored Dec 24, 2020
1 parent 6d2986c commit ccff172
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@

package com.linecorp.armeria.server;

import static java.util.Objects.requireNonNull;

import java.util.function.Function;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;

import com.linecorp.armeria.common.HttpRequest;
import com.linecorp.armeria.common.HttpResponse;

Expand All @@ -24,4 +31,25 @@
*/
@FunctionalInterface
public interface TransientHttpService extends TransientService<HttpRequest, HttpResponse>, HttpService {

/**
* Returns a new {@link HttpService} decorator which makes the specified {@link HttpService} as
* {@link TransientService}.
*/
static Function<? super HttpService, SimpleDecoratingHttpService> newDecorator(
TransientServiceOption... transientServiceOptions) {
requireNonNull(transientServiceOptions, "transientServiceOptions");
return newDecorator(ImmutableSet.copyOf(transientServiceOptions));
}

/**
* Returns a new {@link HttpService} decorator which makes the specified {@link HttpService} as
* {@link TransientService}.
*/
static Function<? super HttpService, SimpleDecoratingHttpService> newDecorator(
Iterable<TransientServiceOption> transientServiceOptions) {
requireNonNull(transientServiceOptions, "transientServiceOptions");
return delegate -> new WrappingTransientHttpService(delegate,
Sets.immutableEnumSet(transientServiceOptions));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@

package com.linecorp.armeria.server;

import static java.util.Objects.requireNonNull;

import java.util.function.Function;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;

import com.linecorp.armeria.common.RpcRequest;
import com.linecorp.armeria.common.RpcResponse;

Expand All @@ -24,4 +31,25 @@
*/
@FunctionalInterface
public interface TransientRpcService extends TransientService<RpcRequest, RpcResponse>, RpcService {

/**
* Returns a new {@link RpcService} decorator which makes the specified {@link RpcService} as
* {@link TransientService}.
*/
static Function<? super RpcService, SimpleDecoratingRpcService> newDecorator(
TransientServiceOption... transientServiceOptions) {
requireNonNull(transientServiceOptions, "transientServiceOptions");
return newDecorator(ImmutableSet.copyOf(transientServiceOptions));
}

/**
* Returns a new {@link RpcService} decorator which makes the specified {@link RpcService} as
* {@link TransientService}.
*/
static Function<? super RpcService, SimpleDecoratingRpcService> newDecorator(
Iterable<TransientServiceOption> transientServiceOptions) {
requireNonNull(transientServiceOptions, "transientServiceOptions");
return delegate -> new WrappingTransientRpcService(delegate,
Sets.immutableEnumSet(transientServiceOptions));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2020 LINE Corporation
*
* LINE Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package com.linecorp.armeria.server;

import java.util.Set;

import com.linecorp.armeria.common.HttpRequest;
import com.linecorp.armeria.common.HttpResponse;

/**
* Decorates a {@link HttpService} to be treated as {@link TransientService} without inheritance.
*/
final class WrappingTransientHttpService extends SimpleDecoratingHttpService implements TransientHttpService {

private final Set<TransientServiceOption> transientServiceOptions;

WrappingTransientHttpService(HttpService delegate, Set<TransientServiceOption> transientServiceOptions) {
super(delegate);
this.transientServiceOptions = transientServiceOptions;
}

@Override
public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exception {
return unwrap().serve(ctx, req);
}

@Override
public Set<TransientServiceOption> transientServiceOptions() {
return transientServiceOptions;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2020 LINE Corporation
*
* LINE Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package com.linecorp.armeria.server;

import java.util.Set;

import com.linecorp.armeria.common.RpcRequest;
import com.linecorp.armeria.common.RpcResponse;

/**
* Decorates a {@link RpcService} to be treated as {@link TransientService} without inheritance.
*/
final class WrappingTransientRpcService extends SimpleDecoratingRpcService implements TransientRpcService {

private final Set<TransientServiceOption> transientServiceOptions;

WrappingTransientRpcService(RpcService delegate, Set<TransientServiceOption> transientServiceOptions) {
super(delegate);
this.transientServiceOptions = transientServiceOptions;
}

@Override
public RpcResponse serve(ServiceRequestContext ctx, RpcRequest req) throws Exception {
return unwrap().serve(ctx, req);
}

@Override
public Set<TransientServiceOption> transientServiceOptions() {
return transientServiceOptions;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2020 LINE Corporation
*
* LINE Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package com.linecorp.armeria.server;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Set;

import org.junit.jupiter.api.Test;

import com.linecorp.armeria.common.HttpResponse;

class WrappingTransientHttpServiceTest {

static final HttpService fooService = (ctx, req) -> HttpResponse.of("foo");

@Test
void extractTransientServiceOptions() {
final HttpService wrapped = fooService.decorate(
TransientHttpService.newDecorator(TransientServiceOption.WITH_ACCESS_LOGGING));

@SuppressWarnings("rawtypes")
final TransientService transientService = wrapped.as(TransientService.class);
assertThat(transientService).isNotNull();

@SuppressWarnings("unchecked")
final Set<TransientServiceOption> transientServiceOptions =
(Set<TransientServiceOption>) transientService.transientServiceOptions();
assertThat(transientServiceOptions).containsExactly(TransientServiceOption.WITH_ACCESS_LOGGING);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2020 LINE Corporation
*
* LINE Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package com.linecorp.armeria.server;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Set;

import org.junit.jupiter.api.Test;

import com.linecorp.armeria.common.RpcResponse;

class WrappingTransientRpcServiceTest {

static final RpcService fooService = (ctx, req) -> RpcResponse.of("foo");

@Test
void extractTransientServiceOptions() {
final RpcService wrapped = fooService.decorate(
TransientRpcService.newDecorator(TransientServiceOption.WITH_ACCESS_LOGGING));

@SuppressWarnings("rawtypes")
final TransientService transientService = wrapped.as(TransientService.class);
assertThat(transientService).isNotNull();

@SuppressWarnings("unchecked")
final Set<TransientServiceOption> transientServiceOptions =
(Set<TransientServiceOption>) transientService.transientServiceOptions();
assertThat(transientServiceOptions).containsExactly(TransientServiceOption.WITH_ACCESS_LOGGING);
}
}

0 comments on commit ccff172

Please sign in to comment.