Skip to content
Snippets Groups Projects
filter.go 3.32 KiB
Newer Older
Ming Deng's avatar
Ming Deng committed
/*
 * 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.
 */

牛学蔚's avatar
牛学蔚 committed
package gshutdown
Ming Deng's avatar
Ming Deng committed

import (
flycash's avatar
flycash committed
	"context"
Ming Deng's avatar
Ming Deng committed
	"sync/atomic"
Ming Deng's avatar
Ming Deng committed
)
Ming Deng's avatar
Ming Deng committed

Ming Deng's avatar
Ming Deng committed
import (
	"dubbo.apache.org/dubbo-go/v3/common/constant"
	"dubbo.apache.org/dubbo-go/v3/common/extension"
	"dubbo.apache.org/dubbo-go/v3/common/logger"
	"dubbo.apache.org/dubbo-go/v3/config"
	"dubbo.apache.org/dubbo-go/v3/filter"
	"dubbo.apache.org/dubbo-go/v3/protocol"
Ming Deng's avatar
Ming Deng committed
)

func init() {
	// `init()` is performed before config.Load(), so shutdownConfig will be retrieved after config was loaded.
	var csf = &Filter{}
	var psf = &Filter{}
牛学蔚's avatar
牛学蔚 committed
	extension.SetFilter(constant.GracefulShutdownConsumerFilterKey, func() filter.Filter {
		return csf
Ming Deng's avatar
Ming Deng committed
	})
牛学蔚's avatar
牛学蔚 committed
	extension.SetFilter(constant.GracefulShutdownProviderFilterKey, func() filter.Filter {
		return psf
Ming Deng's avatar
Ming Deng committed
	})
}

牛学蔚's avatar
牛学蔚 committed
type Filter struct {
Ming Deng's avatar
Ming Deng committed
	activeCount    int32
	shutdownConfig *config.ShutdownConfig
}

// Invoke adds the requests count and block the new requests if application is closing
牛学蔚's avatar
牛学蔚 committed
func (f *Filter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
	if f.rejectNewRequest() {
Ming Deng's avatar
Ming Deng committed
		logger.Info("The application is closing, new request will be rejected.")
牛学蔚's avatar
牛学蔚 committed
		return f.getRejectHandler().RejectedExecution(invoker.GetURL(), invocation)
Ming Deng's avatar
Ming Deng committed
	}
牛学蔚's avatar
牛学蔚 committed
	atomic.AddInt32(&f.activeCount, 1)
flycash's avatar
flycash committed
	return invoker.Invoke(ctx, invocation)
Ming Deng's avatar
Ming Deng committed
}

// OnResponse reduces the number of active processes then return the process result
牛学蔚's avatar
牛学蔚 committed
func (f *Filter) OnResponse(ctx context.Context, result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
	atomic.AddInt32(&f.activeCount, -1)
	// although this isn't thread safe, it won't be a problem if the f.rejectNewRequest() is true.
	if f.shutdownConfig != nil && f.shutdownConfig.RejectRequest && f.activeCount <= 0 {
		f.shutdownConfig.RequestsFinished = true
Ming Deng's avatar
Ming Deng committed
	}
	return result
}

牛学蔚's avatar
牛学蔚 committed
func (f *Filter) Set(name string, conf interface{}) {
	case constant.GracefulShutdownFilterShutdownConfig:
		if shutdownConfig, ok := conf.(*config.ShutdownConfig); ok {
牛学蔚's avatar
牛学蔚 committed
			f.shutdownConfig = shutdownConfig
		logger.Warnf("the type of config for {%s} should be *config.ShutdownConfig", constant.GracefulShutdownFilterShutdownConfig)
牛学蔚's avatar
牛学蔚 committed
func (f *Filter) rejectNewRequest() bool {
	if f.shutdownConfig == nil {
Ming Deng's avatar
Ming Deng committed
		return false
	}
牛学蔚's avatar
牛学蔚 committed
	return f.shutdownConfig.RejectRequest
Ming Deng's avatar
Ming Deng committed
}

牛学蔚's avatar
牛学蔚 committed
func (f *Filter) getRejectHandler() filter.RejectedExecutionHandler {
	handler := constant.DefaultKey
牛学蔚's avatar
牛学蔚 committed
	if f.shutdownConfig != nil && len(f.shutdownConfig.RejectRequestHandler) > 0 {
		handler = f.shutdownConfig.RejectRequestHandler
Ming Deng's avatar
Ming Deng committed
	}
	return extension.GetRejectedExecutionHandler(handler)
}