All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.loadbalancer.reactive.ExecutionContext Maven / Gradle / Ivy

There is a newer version: 2.7.18
Show newest version
/*
 *
 * Copyright 2014 Netflix, Inc.
 *
 * Licensed 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 com.netflix.loadbalancer.reactive;

import com.netflix.client.RetryHandler;
import com.netflix.client.config.IClientConfig;
import com.netflix.client.config.IClientConfigKey;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A context object that is created at start of each load balancer execution
 * and contains certain meta data of the load balancer and mutable state data of 
 * execution per listener per request. Each listener will get its own context
 * to work with. But it can also call {@link ExecutionContext#getGlobalContext()} to
 * get the shared context between all listeners.
 * 
 * @author Allen Wang
 *
 */
public class ExecutionContext {

    private final Map context;
    private final ConcurrentHashMap> subContexts;
    private final T request;
    private final IClientConfig requestConfig;
    private final RetryHandler retryHandler;
    private final IClientConfig clientConfig;

    private static class ChildContext extends ExecutionContext {
        private final ExecutionContext parent;

        ChildContext(ExecutionContext parent) {
            super(parent.request, parent.requestConfig, parent.clientConfig, parent.retryHandler, null);
            this.parent = parent;
        }

        @Override
        public ExecutionContext getGlobalContext() {
            return parent;
        }
    }

    public ExecutionContext(T request, IClientConfig requestConfig, IClientConfig clientConfig, RetryHandler retryHandler) {
        this.request = request;
        this.requestConfig = requestConfig;
        this.clientConfig = clientConfig;
        this.context = new ConcurrentHashMap<>();
        this.subContexts = new ConcurrentHashMap<>();
        this.retryHandler = retryHandler;
    }

    ExecutionContext(T request, IClientConfig requestConfig, IClientConfig clientConfig, RetryHandler retryHandler, ConcurrentHashMap> subContexts) {
        this.request = request;
        this.requestConfig = requestConfig;
        this.clientConfig = clientConfig;
        this.context = new ConcurrentHashMap<>();
        this.subContexts = subContexts;
        this.retryHandler = retryHandler;
    }


    ExecutionContext getChildContext(Object obj) {
        if (subContexts == null) {
            return null;
        }
        ChildContext subContext = subContexts.get(obj);
        if (subContext == null) {
            subContext = new ChildContext(this);
            ChildContext old = subContexts.putIfAbsent(obj, subContext);
            if (old != null) {
                subContext = old;
            }
        }
        return subContext;
    }

    public T getRequest() {
        return request;
    }

    public Object get(String name) {
        return context.get(name);
    }

    public  S getClientProperty(IClientConfigKey key) {
        S value;
        if (requestConfig != null) {
            value = requestConfig.get(key);
            if (value != null) {
                return value;
            }
        }
        value = clientConfig.get(key);
        return value;
    }
    
    public void put(String name, Object value) {
        context.put(name, value);
    }

    /**
     * @return The IClientConfig object used to override the client's default configuration
     * for this specific execution.
     */
    public IClientConfig getRequestConfig() {
        return requestConfig;
    }

    /**
     *
     * @return The shared context for all listeners.
     */
    public ExecutionContext getGlobalContext() {
        return this;
    }

    public RetryHandler getRetryHandler() {
        return retryHandler;
    }
}