Skip to content

Commit

Permalink
Polish apache#4807 : [Feature] Add the callback mechanism ShutdownHook
Browse files Browse the repository at this point in the history
  • Loading branch information
mercyblitz committed Aug 13, 2019
1 parent c284dad commit 3d84c35
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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
*
* http://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 org.apache.dubbo.common.lang;

import static java.lang.Integer.compare;

/**
* {@code Prioritized} interface can be implemented by objects that
* should be sorted, for example the tasks in executable queue.
*
* @since 2.7.4
*/
public interface Prioritized extends Comparable<Prioritized> {

/**
* The maximum priority
*/
int MAX_PRIORITY = Integer.MIN_VALUE;

/**
* The minimum priority
*/
int MIN_PRIORITY = Integer.MAX_VALUE;

/**
* Get the priority
*
* @return the default is {@link #MIN_PRIORITY minimum one}
*/
default int getPriority() {
return MIN_PRIORITY;
}

@Override
default int compareTo(Prioritized that) {
return compare(this.getPriority(), that.getPriority());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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
*
* http://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 org.apache.dubbo.common.lang;

/**
* Dubbo ShutdownHook callback interface
*
* @since 2.7.4
*/
public interface ShutdownHookCallback extends Prioritized {

/**
* Callback execution
*
* @throws Throwable if met with some errors
*/
void callback() throws Throwable;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.apache.dubbo.config;

import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.lang.ShutdownHookCallback;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.config.event.DubboServiceDestroyedEvent;
Expand All @@ -27,8 +28,14 @@
import org.apache.dubbo.registry.support.AbstractRegistryFactory;
import org.apache.dubbo.rpc.Protocol;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import static java.util.Collections.sort;
import static java.util.ServiceLoader.load;

/**
* The shutdown hook thread to do the clean up stuff.
* This is a singleton in order to ensure there is only one shutdown hook registered.
Expand All @@ -40,19 +47,29 @@ public class DubboShutdownHook extends Thread {
private static final Logger logger = LoggerFactory.getLogger(DubboShutdownHook.class);

private static final DubboShutdownHook DUBBO_SHUTDOWN_HOOK = new DubboShutdownHook("DubboShutdownHook");

/**
* Has it already been registered or not?
*/
private final AtomicBoolean registered = new AtomicBoolean(false);

/**
* Has it already been destroyed or not?
*/
private final AtomicBoolean destroyed = new AtomicBoolean(false);

private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension();

private final List<ShutdownHookCallback> callbacks = new LinkedList<>();

private DubboShutdownHook(String name) {
super(name);
loadCallbacks();
}

public DubboShutdownHook addCallback(ShutdownHookCallback callback) {
this.callbacks.add(callback);
return this;
}

public static DubboShutdownHook getDubboShutdownHook() {
Expand All @@ -64,9 +81,41 @@ public void run() {
if (logger.isInfoEnabled()) {
logger.info("Run shutdown hook now.");
}
callback();
doDestroy();
}

/**
* For testing purpose
*/
Collection<ShutdownHookCallback> getCallbacks() {
sort(callbacks);
return callbacks;
}

/**
* For testing purpose
*/
void clear() {
callbacks.clear();
}

private void loadCallbacks() {
load(ShutdownHookCallback.class).forEach(callbacks::add);
}

private void callback() {
getCallbacks().forEach(callback -> {
try {
callback.callback();
} catch (Throwable e) {
if (logger.isErrorEnabled()) {
logger.error(e.getMessage(), e);
}
}
});
}

/**
* Register the ShutdownHook
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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
*
* http://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 org.apache.dubbo.config;

import org.apache.dubbo.common.lang.ShutdownHookCallback;
import org.apache.dubbo.event.EventDispatcher;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

/**
* {@link DubboShutdownHook} Test
*
* @since 2.7.4
*/
public class DubboShutdownHookTest implements ShutdownHookCallback {

private final DubboShutdownHook dubboShutdownHook = DubboShutdownHook.getDubboShutdownHook();

private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension();


@BeforeEach
public void before() {

}

@AfterEach
public void after() {
eventDispatcher.removeAllEventListeners();
dubboShutdownHook.clear();
}

@Test
public void testCallback() {
assertEquals(this.getClass(), dubboShutdownHook.getCallbacks().iterator().next().getClass());
dubboShutdownHook.addCallback(this);
assertEquals(2, dubboShutdownHook.getCallbacks().size());
}

@Override
public void callback() throws Throwable {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.apache.dubbo.config.DubboShutdownHookTest

0 comments on commit 3d84c35

Please sign in to comment.