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

Introduce ContextAwareRunnable|Callable|Function|Consume|BiConsumer|BiFunction #4890

Merged
merged 2 commits into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2023 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.common;

import java.util.function.BiConsumer;

import com.linecorp.armeria.common.annotation.UnstableApi;

/**
* A delegating {@link BiConsumer} that makes sure an underlying BiConsumer is
* executed within the {@link RequestContext}.
*/
@UnstableApi
public interface ContextAwareBiConsumer<T, U> extends BiConsumer<T, U>, ContextHolder {

/**
* Returns a new {@link ContextAwareBiConsumer} that sets the specified {@link RequestContext}
* before executing an underlying {@link BiConsumer}.
*/
static <T, U> ContextAwareBiConsumer of(RequestContext context, BiConsumer<T, U> action) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds two public APIs for doing the same thing I think

ContextAwareBiConsumer.of(ctx, action)
ctx.makeContextAware(action)

Probably it's better to avoid these factory methods since the context has them already

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was mostly following the pattern that's already in place with things like ContextAwareExecutor.

Don't feel strongly about it either way but since we can't (yet) change the type returned from ctx.makeX, maybe leaving another API (ContextAwareBiConsumer) around isn't a bad idea to help users avoid type casting.

return new DefaultContextAwareBiConsumer(context, action);
}

/**
* Returns the {@link RequestContext} that was specified when creating
* this {@link ContextAwareBiConsumer}.
*/
@Override
RequestContext context();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And another idea as another alternative to the static methods could be a common interface for context aware callbacks

interface ContextAwareCallback<T> {
  RequestContext context();
  T withoutContext();
}

class DefaultContextAwareBiConsumer<T, U> implements BiConsumer<T, U>, ContextAwareCallback<BiConsumer<T, U>> {
}

In the meantime if the caller needs to type cast, they would only have one type to worry about.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd actually imagine ContextHolder would be a popular type-cast. At least, that's what I'm going to do internally.


/**
* Returns the {@link BiConsumer} that's executed without setting
* the {@link RequestContext}.
*/
BiConsumer<T, U> withoutContext();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2023 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.common;

import java.util.function.BiFunction;

import com.linecorp.armeria.common.annotation.UnstableApi;

/**
* A delegating {@link BiFunction} that makes sure an underlying BiFunction is
* executed within the {@link RequestContext}.
*/
@UnstableApi
public interface ContextAwareBiFunction<T, U, R> extends BiFunction<T, U, R>, ContextHolder {

/**
* Returns a new {@link ContextAwareBiFunction} that sets the specified {@link RequestContext}
* before executing an underlying {@link BiFunction}.
*/
static <T, U, R> ContextAwareBiFunction of(RequestContext context, BiFunction<T, U, R> function) {
return new DefaultContextAwareBiFunction(context, function);
}

/**
* Returns the {@link RequestContext} that was specified when creating
* this {@link ContextAwareBiFunction}.
*/
@Override
RequestContext context();

/**
* Returns the {@link BiFunction} that's executed without setting
* the {@link RequestContext}.
*/
BiFunction<T, U, R> withoutContext();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2023 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.common;

import java.util.concurrent.Callable;

import com.linecorp.armeria.common.annotation.UnstableApi;

/**
* A delegating {@link Callable} that makes sure an underlying Callable is
* executed within the {@link RequestContext}.
*/
@UnstableApi
public interface ContextAwareCallable<T> extends Callable<T>, ContextHolder {
vkostyukov marked this conversation as resolved.
Show resolved Hide resolved

/**
* Returns a new {@link ContextAwareCallable} that sets the specified {@link RequestContext}
* before executing an underlying {@link Callable}.
*/
static <T> ContextAwareCallable<T> of(RequestContext context, Callable<T> callable) {
return new DefaultContextAwareCallable<T>(context, callable);
}

/**
* Returns the {@link RequestContext} that was specified when creating
* this {@link ContextAwareCallable}.
*/
@Override
RequestContext context();

/**
* Returns the {@link Callable} that's executed without setting
* the {@link RequestContext}.
*/
Callable<T> withoutContext();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2023 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.common;

import java.util.function.Consumer;

import com.linecorp.armeria.common.annotation.UnstableApi;

/**
* A delegating {@link Consumer} that makes sure an underlying Consumer is
* executed within the {@link RequestContext}.
*/
@UnstableApi
public interface ContextAwareConsumer<T> extends Consumer<T>, ContextHolder {

/**
* Returns a new {@link ContextAwareConsumer} that sets the specified {@link RequestContext}
* before executing an underlying {@link Consumer}.
*/
static <T, R> ContextAwareConsumer of(RequestContext context, Consumer<T> action) {
return new DefaultContextAwareConsumer(context, action);
}

/**
* Returns the {@link RequestContext} that was specified when creating
* this {@link ContextAwareConsumer}.
*/
@Override
RequestContext context();

/**
* Returns the {@link Consumer} that's executed without setting
* the {@link RequestContext}.
*/
Consumer<T> withoutContext();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2023 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.common;

import java.util.function.Function;

import com.linecorp.armeria.common.annotation.UnstableApi;

/**
* A delegating {@link Function} that makes sure an underlying Function is
* executed within the {@link RequestContext}.
*/
@UnstableApi
public interface ContextAwareFunction<T, R> extends Function<T, R>, ContextHolder {

/**
* Returns a new {@link ContextAwareFuture} that sets the specified {@link RequestContext}
* before executing an underlying {@link Function}.
*/
static <T, R> ContextAwareFunction of(RequestContext context, Function<T, R> function) {
return new DefaultContextAwareFunction(context, function);
}

/**
* Returns the {@link RequestContext} that was specified when creating
* this {@link ContextAwareFunction}.
*/
@Override
RequestContext context();

/**
* Returns the {@link Function} that's executed without setting
* the {@link RequestContext}.
*/
Function<T, R> withoutContext();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2023 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.common;

import com.linecorp.armeria.common.annotation.UnstableApi;

/**
* A delegating {@link Runnable} that makes sure an underlying Runnable is
* executed within the {@link RequestContext}.
*/
@UnstableApi
public interface ContextAwareRunnable extends Runnable, ContextHolder {
vkostyukov marked this conversation as resolved.
Show resolved Hide resolved

/**
* Returns a new {@link ContextAwareRunnable} that sets the specified {@link RequestContext}
* before executing an underlying {@link Runnable}.
*/
static ContextAwareRunnable of(RequestContext context, Runnable runnable) {
return new DefaultContextAwareRunnable(context, runnable);
}

/**
* Returns the {@link RequestContext} that was specified when creating
* this {@link ContextAwareRunnable}.
*/
@Override
RequestContext context();

/**
* Returns the {@link Runnable} that's executed without setting
* the {@link RequestContext}.
*/
Runnable withoutContext();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2023 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.common;

import static java.util.Objects.requireNonNull;

import java.util.function.BiConsumer;

import com.linecorp.armeria.common.util.SafeCloseable;

final class DefaultContextAwareBiConsumer<T, U> implements ContextAwareBiConsumer<T, U> {
private final RequestContext context;
private final BiConsumer<T, U> action;

DefaultContextAwareBiConsumer(RequestContext context, BiConsumer<T, U> action) {
this.context = requireNonNull(context, "context");
this.action = requireNonNull(action, "action");
}

@Override
public RequestContext context() {
return context;
}

@Override
public BiConsumer<T, U> withoutContext() {
return action;
}

@Override
public void accept(T t, U u) {
try (SafeCloseable ignored = context.push()) {
action.accept(t, u);
}
}
}
Loading