This commit is contained in:
shuhongfan
2023-09-04 16:40:17 +08:00
commit cf5ac25c14
8267 changed files with 1305066 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sentinel-cluster</artifactId>
<groupId>com.alibaba.csp</groupId>
<version>1.8.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sentinel-cluster-common-default</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,48 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster;
/**
* @author Eric Zhao
* @since 1.4.0
*/
public final class ClusterConstants {
public static final int MSG_TYPE_PING = 0;
public static final int MSG_TYPE_FLOW = 1;
public static final int MSG_TYPE_PARAM_FLOW = 2;
public static final int MSG_TYPE_CONCURRENT_FLOW_ACQUIRE = 3;
public static final int MSG_TYPE_CONCURRENT_FLOW_RELEASE = 4;
public static final int RESPONSE_STATUS_BAD = -1;
public static final int RESPONSE_STATUS_OK = 0;
public static final int PARAM_TYPE_INTEGER = 0;
public static final int PARAM_TYPE_LONG = 1;
public static final int PARAM_TYPE_BYTE = 2;
public static final int PARAM_TYPE_DOUBLE = 3;
public static final int PARAM_TYPE_FLOAT = 4;
public static final int PARAM_TYPE_SHORT = 5;
public static final int PARAM_TYPE_BOOLEAN = 6;
public static final int PARAM_TYPE_STRING = 7;
public static final int DEFAULT_CLUSTER_SERVER_PORT = 18730;
public static final int DEFAULT_REQUEST_TIMEOUT = 20;
public static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 10 * 1000;
private ClusterConstants() {}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster;
/**
* @author jialiang.ljl
* @since 1.4.0
*/
public final class ClusterErrorMessages {
public static final String BAD_REQUEST = "bad request";
public static final String UNEXPECTED_STATUS = "unexpected status";
public static final String TOO_MANY_REQUESTS = "too many requests (client side)";
public static final String REQUEST_TIME_OUT = "request time out";
public static final String CLIENT_NOT_READY = "client not ready";
public static final String NO_RULES_IN_SERVER = "no rules in token server";
private ClusterErrorMessages() {}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster;
import com.alibaba.csp.sentinel.cluster.request.ClusterRequest;
import com.alibaba.csp.sentinel.cluster.response.ClusterResponse;
/**
* Synchronous transport client for distributed flow control.
*
* @author Eric Zhao
* @since 1.4.0
*/
public interface ClusterTransportClient {
/**
* Start the client.
*
* @throws Exception some error occurred (e.g. initialization failed)
*/
void start() throws Exception;
/**
* Stop the client.
*
* @throws Exception some error occurred (e.g. shutdown failed)
*/
void stop() throws Exception;
/**
* Send request to remote server and get response.
*
* @param request Sentinel cluster request
* @return response from remote server
* @throws Exception some error occurs
*/
ClusterResponse sendRequest(ClusterRequest request) throws Exception;
/**
* Check whether the client has been started and ready for sending requests.
*
* @return true if the client is ready to send requests, otherwise false
*/
boolean isReady();
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Request type annotation for handlers, codes, etc.
*
* @author Eric Zhao
* @since 1.4.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
public @interface RequestType {
/**
* Type of the request to handle.
*
* @return type of the request
*/
int value();
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.codec;
/**
* @param <S> source stream type
* @param <T> target entity type
* @author Eric Zhao
* @since 1.4.0
*/
public interface EntityDecoder<S, T> {
/**
* Decode target object from source stream.
*
* @param source source stream
* @return decoded target object
*/
T decode(S source);
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.codec;
/**
* A universal interface for publishing entities to a target stream.
*
* @param <E> entity type
* @param <T> target stream type
* @author Eric Zhao
* @since 1.4.0
*/
public interface EntityWriter<E, T> {
/**
* Write the provided entity to target stream.
*
* @param entity entity to publish
* @param target the target stream
*/
void writeTo(E entity, T target);
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.codec.request;
import com.alibaba.csp.sentinel.cluster.codec.EntityDecoder;
import com.alibaba.csp.sentinel.cluster.request.Request;
/**
* @author Eric Zhao
* @since 1.4.0
*/
public interface RequestEntityDecoder<S, T extends Request> extends EntityDecoder<S, T> {
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.codec.request;
import com.alibaba.csp.sentinel.cluster.codec.EntityWriter;
import com.alibaba.csp.sentinel.cluster.request.Request;
/**
* A universal {@link EntityWriter} interface for publishing {@link Request} to a target stream.
*
* @author Eric Zhao
* @since 1.4.0
*/
public interface RequestEntityWriter<E extends Request, T> extends EntityWriter<E, T> {
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.codec.response;
import com.alibaba.csp.sentinel.cluster.codec.EntityDecoder;
import com.alibaba.csp.sentinel.cluster.response.Response;
/**
* @author Eric Zhao
* @since 1.4.0
*/
public interface ResponseEntityDecoder<S, T extends Response> extends EntityDecoder<S, T> {
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.codec.response;
import com.alibaba.csp.sentinel.cluster.codec.EntityWriter;
import com.alibaba.csp.sentinel.cluster.response.Response;
/**
* A universal {@link EntityWriter} interface for publishing {@link Response} to a target stream.
*
* @author Eric Zhao
* @since 1.4.0
*/
public interface ResponseEntityWriter<E extends Response, T> extends EntityWriter<E, T> {
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.exception;
/**
* @author jialiang.ljl
* @since 1.4.0
*/
public class SentinelClusterException extends Exception {
public SentinelClusterException(String errorMsg) {
super(errorMsg);
}
@Override
public Throwable fillInStackTrace() {
return this;
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.registry;
import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.util.AppNameUtil;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.csp.sentinel.util.function.Supplier;
/**
* @author Eric Zhao
* @since 1.4.0
*/
public final class ConfigSupplierRegistry {
/**
* The default namespace supplier provides appName as namespace.
*/
private static final Supplier<String> DEFAULT_APP_NAME_SUPPLIER = new Supplier<String>() {
@Override
public String get() {
return AppNameUtil.getAppName();
}
};
/**
* Registered namespace supplier.
*/
private static Supplier<String> namespaceSupplier = DEFAULT_APP_NAME_SUPPLIER;
/**
* Get the registered namespace supplier.
*
* @return the registered namespace supplier
*/
public static Supplier<String> getNamespaceSupplier() {
return namespaceSupplier;
}
public static void setNamespaceSupplier(Supplier<String> namespaceSupplier) {
AssertUtil.notNull(namespaceSupplier, "namespaceSupplier cannot be null");
ConfigSupplierRegistry.namespaceSupplier = namespaceSupplier;
RecordLog.info("[ConfigSupplierRegistry] New namespace supplier provided, current supplied: {}",
namespaceSupplier.get());
}
private ConfigSupplierRegistry() {}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.request;
/**
* @author Eric Zhao
* @since 1.4.0
*/
public class ClusterRequest<T> implements Request {
private int id;
private int type;
private T data;
public ClusterRequest() {}
public ClusterRequest(int id, int type, T data) {
this.id = id;
this.type = type;
this.data = data;
}
public ClusterRequest(int type, T data) {
this.type = type;
this.data = data;
}
@Override
public int getId() {
return id;
}
public ClusterRequest<T> setId(int id) {
this.id = id;
return this;
}
@Override
public int getType() {
return type;
}
public ClusterRequest<T> setType(int type) {
this.type = type;
return this;
}
public T getData() {
return data;
}
public ClusterRequest<T> setData(T data) {
this.data = data;
return this;
}
@Override
public String toString() {
return "ClusterRequest{" +
"id=" + id +
", type=" + type +
", data=" + data +
'}';
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.request;
/**
* Cluster transport request interface.
*
* @author Eric Zhao
* @since 1.4.0
*/
public interface Request {
/**
* Get request type.
*
* @return request type
*/
int getType();
/**
* Get request ID.
*
* @return unique request ID
*/
int getId();
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.request.data;
/**
* @author Eric Zhao
* @since 1.4.0
*/
public class FlowRequestData {
private long flowId;
private int count;
private boolean priority;
public long getFlowId() {
return flowId;
}
public FlowRequestData setFlowId(long flowId) {
this.flowId = flowId;
return this;
}
public int getCount() {
return count;
}
public FlowRequestData setCount(int count) {
this.count = count;
return this;
}
public boolean isPriority() {
return priority;
}
public FlowRequestData setPriority(boolean priority) {
this.priority = priority;
return this;
}
@Override
public String toString() {
return "FlowRequestData{" +
"flowId=" + flowId +
", count=" + count +
", priority=" + priority +
'}';
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.request.data;
import java.util.Collection;
/**
* @author Eric Zhao
* @since 1.4.0
*/
public class ParamFlowRequestData {
private long flowId;
private int count;
private Collection<Object> params;
public long getFlowId() {
return flowId;
}
public ParamFlowRequestData setFlowId(long flowId) {
this.flowId = flowId;
return this;
}
public int getCount() {
return count;
}
public ParamFlowRequestData setCount(int count) {
this.count = count;
return this;
}
public Collection<Object> getParams() {
return params;
}
public ParamFlowRequestData setParams(Collection<Object> params) {
this.params = params;
return this;
}
@Override
public String toString() {
return "ParamFlowRequestData{" +
"flowId=" + flowId +
", count=" + count +
", params=" + params +
'}';
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.response;
/**
* @author Eric Zhao
* @since 1.4.0
*/
public class ClusterResponse<T> implements Response {
private int id;
private int type;
private int status;
private T data;
public ClusterResponse() {}
public ClusterResponse(int id, int type, int status, T data) {
this.id = id;
this.type = type;
this.status = status;
this.data = data;
}
@Override
public int getId() {
return id;
}
public ClusterResponse<T> setId(int id) {
this.id = id;
return this;
}
@Override
public int getType() {
return type;
}
public ClusterResponse<T> setType(int type) {
this.type = type;
return this;
}
@Override
public int getStatus() {
return status;
}
public ClusterResponse<T> setStatus(int status) {
this.status = status;
return this;
}
public T getData() {
return data;
}
public ClusterResponse<T> setData(T data) {
this.data = data;
return this;
}
@Override
public String toString() {
return "ClusterResponse{" +
"id=" + id +
", type=" + type +
", status=" + status +
", data=" + data +
'}';
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.response;
/**
* Cluster transport response interface.
*
* @author Eric Zhao
* @since 1.4.0
*/
public interface Response {
/**
* Get response ID.
*
* @return response ID
*/
int getId();
/**
* Get response type.
*
* @return response type
*/
int getType();
/**
* Get response status.
*
* @return response status
*/
int getStatus();
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.cluster.response.data;
/**
* @author Eric Zhao
* @since 1.4.0
*/
public class FlowTokenResponseData {
private int remainingCount;
private int waitInMs;
public int getRemainingCount() {
return remainingCount;
}
public FlowTokenResponseData setRemainingCount(int remainingCount) {
this.remainingCount = remainingCount;
return this;
}
public int getWaitInMs() {
return waitInMs;
}
public FlowTokenResponseData setWaitInMs(int waitInMs) {
this.waitInMs = waitInMs;
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof FlowTokenResponseData)) {
return false;
}
FlowTokenResponseData that = (FlowTokenResponseData) o;
return this.remainingCount == that.remainingCount && this.waitInMs == that.waitInMs;
}
@Override
public int hashCode() {
int result = remainingCount;
result = 31 * result + waitInMs;
return result;
}
@Override
public String toString() {
return "FlowTokenResponseData{" +
"remainingCount=" + remainingCount +
", waitInMs=" + waitInMs +
'}';
}
}