/**
* Copyright 2024 Beijing Baolande Software Corporation
*
* 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.
*
* Runtime Library Exception to the Apache 2.0 License:
*
* As an exception, if you use this Software to compile your source code and
* portions of this Software are embedded into the binary product as a result,
* you may redistribute such product without providing attribution as would
* otherwise be required by Sections 4(a), 4(b) and 4(d) of the License.
*/
package redis_sdk.client
public abstract class RedisClientConfigBase {
private var respVersionVal: ?ProtocolVersion = None
private var userVal: ?String = None
private var passwordVal: ?Array<Byte> = None
private var clientNameVal: ?String = None
/**
* 发送Redis命令后,等待响应到达的超时时间
*/
private var waitResponseTimeoutVal = Duration.minute * 5
// 默认300毫秒
private var shutdownTimeoutVal: Duration = Duration.millisecond * 300
private var waitConnectionTimeoutVal: Duration = Duration.second * 30
private var checkSubscribeMessageIntervalVal: Duration = Duration.second * 30
// 每个Socket连接使用专有的写线程
private var asyncWriteVal: Bool = true
// 写队列长度,asyncWrite为true时使用
private var writeQueueSizeVal: Int64 = 8192
// 写缓冲区大小,asyncWrite为true时使用,可以减少Socket write系统调用
private var writeBufferSizeVal: Int64 = 8192
// 为每个连接固定一个读数据的线程
private var stickyReadVal: Bool = true
// 在读线程上执行编解码
private var execOnReadThreadVal: Bool = true
// 将要处理的消息报文从读缓存通过片的方式分割出来,可以减少数组的拷贝
private var sliceExceedBufferVal: Bool = true
/**
* 能处理的最大消息长度
*/
private var maxMessageSizeInBytesVal: Int64 = 64 * 1024 * 1024
private var receiveBufferSizeVal: ?Int64 = None
private var sendBufferSizeVal: ?Int64 = None
private var noDelayVal: ?Bool = None
private var lingerVal: ?Duration = None
private var readTimeoutVal: ?Duration = None
private var writeTimeoutVal: ?Duration = None
private var idleTimeoutVal: Duration = Duration.minute * 20
/**
* 默认分配的ByteBuffer的容量
*
*/
private var bufferAllocateSizeVal: Int64 = 8192
/**
* 是否将ByteBuffer缓存到池中
*
*/
private var usePooledBufferAllocatorVal: Bool = false
/**
* 最大缓存的ByteBuffer的数量
*
*/
private var maxPooledBuffersVal: Int64 = 2048
private var threadPoolNameVal: String = "RedisClient"
private var threadPoolQueueSizeVal: Int64 = 4096
private var maxThreadsVal: Int64 = 256
private var minThreadsVal: Int64 = 0
private var threadIdleTimeoutVal: Duration = Duration.minute * 2
/**
* 持久化订阅的最大恢复时间
*/
private var maxSubscriberRecoverDurationVal = Duration.minute * 20
/**
* 持久化订阅每分钟尝试的恢复次数
*/
private var recoverAttemptsPerMinuteVal = 3
// 使用允许取出的连接被多个线程并发操作的连接池
private var useNonExclusiveObjectPoolVal: Bool = false
private var objectPoolEvictionIntervalsVal: ?Duration = None
private var objectPoolLifoVal: Bool = true
private var testOnCreateVal: Bool = false
private var testOnBorrowVal: Bool = true
private var testOnReturnVal: Bool = false
private var testWhileIdleVal: Bool = false
public mut prop respVersion: ?ProtocolVersion {
get() {
return respVersionVal
}
set(value) {
this.respVersionVal = value
}
}
public mut prop user: ?String {
get() {
return userVal
}
set(value) {
this.userVal = value
}
}
public mut prop password: ?Array<Byte> {
get() {
return passwordVal
}
set(value) {
this.passwordVal = value
}
}
public mut prop clientName: ?String {
get() {
return clientNameVal
}
set(value) {
this.clientNameVal = value
}
}
public mut prop waitResponseTimeout: Duration {
get() {
return waitResponseTimeoutVal
}
set(value) {
if (value > Duration.Zero) {
this.waitResponseTimeoutVal = value
}
}
}
public mut prop shutdownTimeout: Duration {
get() {
return shutdownTimeoutVal
}
set(value) {
this.shutdownTimeoutVal = value
}
}
public mut prop waitConnectionTimeout: Duration {
get() {
return waitConnectionTimeoutVal
}
set(value) {
this.waitConnectionTimeoutVal = value
}
}
public mut prop checkSubscribeMessageInterval: Duration {
get() {
return checkSubscribeMessageIntervalVal
}
set(value) {
this.checkSubscribeMessageIntervalVal = value
}
}
public mut prop asyncWrite: Bool {
get() {
return asyncWriteVal
}
set(value) {
this.asyncWriteVal = value
}
}
public mut prop writeQueueSize: Int64 {
get() {
writeQueueSizeVal
}
set(v) {
if (v > 0) {
this.writeQueueSizeVal = v
}
}
}
public mut prop writeBufferSize: Int64 {
get() {
writeBufferSizeVal
}
set(v) {
if (v > 0) {
this.writeBufferSizeVal = v
}
}
}
public mut prop stickyRead: Bool {
get() {
stickyReadVal
}
set(v) {
this.stickyReadVal = v
}
}
public mut prop execOnReadThread: Bool {
get() {
execOnReadThreadVal
}
set(v) {
this.execOnReadThreadVal = v
}
}
public mut prop sliceExceedBuffer: Bool {
get() {
sliceExceedBufferVal
}
set(v) {
this.sliceExceedBufferVal = v
}
}
public mut prop maxMessageSizeInBytes: Int64 {
get() {
maxMessageSizeInBytesVal
}
set(v) {
if (v > 0) {
this.maxMessageSizeInBytesVal = v
}
}
}
public mut prop receiveBufferSize: ?Int64 {
get() {
return receiveBufferSizeVal
}
set(value) {
this.receiveBufferSizeVal = value
}
}
public mut prop sendBufferSize: ?Int64 {
get() {
return sendBufferSizeVal
}
set(value) {
this.sendBufferSizeVal = value
}
}
public mut prop noDelay: ?Bool {
get() {
return noDelayVal
}
set(value) {
this.noDelayVal = value
}
}
public mut prop linger: ?Duration {
get() {
return lingerVal
}
set(value) {
this.lingerVal = value
}
}
public mut prop readTimeout: ?Duration {
get() {
return readTimeoutVal
}
set(value) {
this.readTimeoutVal = value
}
}
public mut prop writeTimeout: ?Duration {
get() {
return writeTimeoutVal
}
set(value) {
this.writeTimeoutVal = value
}
}
public mut prop idleTimeout: Duration {
get() {
return idleTimeoutVal
}
set(value) {
this.idleTimeoutVal = value
}
}
public mut prop bufferAllocateSize: Int64 {
get() {
bufferAllocateSizeVal
}
set(v) {
if (v > 0 && v < maxMessageSizeInBytesVal) {
this.bufferAllocateSizeVal = v
}
}
}
public mut prop usePooledBufferAllocator: Bool {
get() {
usePooledBufferAllocatorVal
}
set(v) {
this.usePooledBufferAllocatorVal = v
}
}
public mut prop maxPooledBuffers: Int64 {
get() {
maxPooledBuffersVal
}
set(v) {
if (v > 0) {
this.maxPooledBuffersVal = v
}
}
}
public mut prop threadPoolName: String {
get() {
return threadPoolNameVal
}
set(value) {
this.threadPoolNameVal = value
}
}
public mut prop threadPoolQueueSize: Int64 {
get() {
return threadPoolQueueSizeVal
}
set(value) {
this.threadPoolQueueSizeVal = value
}
}
public mut prop maxThreads: Int64 {
get() {
return maxThreadsVal
}
set(value) {
this.maxThreadsVal = value
}
}
public mut prop minThreads: Int64 {
get() {
return minThreadsVal
}
set(value) {
this.minThreadsVal = value
}
}
public mut prop threadIdleTimeout: Duration {
get() {
return threadIdleTimeoutVal
}
set(value) {
this.threadIdleTimeoutVal = value
}
}
public mut prop maxSubscriberRecoverDuration: Duration {
get() {
return maxSubscriberRecoverDurationVal
}
set(value) {
this.maxSubscriberRecoverDurationVal = value
}
}
public mut prop recoverAttemptsPerMinute: Int64 {
get() {
return recoverAttemptsPerMinuteVal
}
set(value) {
this.recoverAttemptsPerMinuteVal = value
}
}
public mut prop useNonExclusiveObjectPool: Bool {
get() {
return useNonExclusiveObjectPoolVal
}
set(value) {
this.useNonExclusiveObjectPoolVal = value
}
}
public mut prop objectPoolEvictionIntervals: ?Duration {
get() {
return objectPoolEvictionIntervalsVal
}
set(value) {
this.objectPoolEvictionIntervalsVal = value
}
}
public mut prop objectPoolLifo: Bool {
get() {
return objectPoolLifoVal
}
set(value) {
this.objectPoolLifoVal = value
}
}
public mut prop testOnCreate: Bool {
get() {
return testOnCreateVal
}
set(value) {
this.testOnCreateVal = value
}
}
public mut prop testOnBorrow: Bool {
get() {
return testOnBorrowVal
}
set(value) {
this.testOnBorrowVal = value
}
}
public mut prop testOnReturn: Bool {
get() {
return testOnReturnVal
}
set(value) {
this.testOnReturnVal = value
}
}
public mut prop testWhileIdle: Bool {
get() {
return testWhileIdleVal
}
set(value) {
this.testWhileIdleVal = value
}
}
public open func configTcpEndpointOptions(endpoint: ClientEndpointConfig) {
endpoint.waitConnectionTimeout = waitConnectionTimeout
endpoint.asyncWrite = this.asyncWrite
endpoint.writeQueueSize = this.writeQueueSize
endpoint.writeBufferSize = this.writeBufferSize
endpoint.stickyRead = this.stickyRead
endpoint.execOnReadThread = this.execOnReadThread
endpoint.sliceExceedBuffer = this.sliceExceedBuffer
endpoint.maxMessageSizeInBytes = this.maxMessageSizeInBytes
if (let Some(receiveBufferSize) <- this.receiveBufferSize) {
if (receiveBufferSize > 0) {
endpoint.receiveBufferSize = receiveBufferSize
}
}
if (let Some(sendBufferSize) <- this.sendBufferSize) {
if (sendBufferSize > 0) {
endpoint.sendBufferSize = sendBufferSize
}
}
if (let Some(noDelay) <- this.noDelay) {
endpoint.noDelay = noDelay
}
if (let Some(linger) <- this.linger) {
endpoint.linger = linger
}
if (let Some(readTimeout) <- this.readTimeout) {
endpoint.readTimeout = readTimeout
}
if (let Some(writeTimeout) <- this.writeTimeout) {
endpoint.writeTimeout = writeTimeout
}
endpoint.idleTimeout = this.idleTimeout
endpoint.bufferAllocateSize = this.bufferAllocateSize
endpoint.usePooledBufferAllocator = this.usePooledBufferAllocator
endpoint.maxPooledBuffers = this.maxPooledBuffers
endpoint.lifo = this.objectPoolLifo
endpoint.useNonExclusiveObjectPool = this.useNonExclusiveObjectPool
if (let Some(objectPoolEvictionIntervals) <- this.objectPoolEvictionIntervals) {
endpoint.evictionIntervals = objectPoolEvictionIntervals
}
endpoint.testOnCreate = this.testOnCreate
endpoint.testOnBorrow = this.testOnBorrow
endpoint.testOnReturn = this.testOnReturn
endpoint.testWhileIdle = this.testWhileIdle
}
@OverflowWrapping
public open func computeHashCode(): Int64 {
let prime = 53
var hashCode = 0
if (let Some(respVersion) <- respVersionVal) {
hashCode = hashCode + prime * respVersion.hashCode()
}
if (let Some(user) <- userVal) {
hashCode = hashCode + prime * user.hashCode()
}
if (let Some(password) <- passwordVal) {
hashCode = hashCode + prime * String.fromUtf8(password).hashCode()
}
if (let Some(clientName) <- clientNameVal) {
hashCode = hashCode + prime * clientName.hashCode()
}
hashCode = hashCode + prime * shutdownTimeoutVal.hashCode()
hashCode = hashCode + prime * waitConnectionTimeoutVal.hashCode()
hashCode = hashCode + prime * checkSubscribeMessageIntervalVal.hashCode()
hashCode = hashCode + prime * asyncWriteVal.hashCode()
hashCode = hashCode + prime * writeQueueSize.hashCode()
hashCode = hashCode + prime * writeBufferSize.hashCode()
hashCode = hashCode + prime * stickyRead.hashCode()
hashCode = hashCode + prime * execOnReadThread.hashCode()
if (let Some(receiveBufferSize) <- receiveBufferSizeVal) {
hashCode = hashCode + prime * receiveBufferSize.hashCode()
}
if (let Some(sendBufferSize) <- sendBufferSizeVal) {
hashCode = hashCode + prime * sendBufferSize.hashCode()
}
if (let Some(noDelay) <- noDelayVal) {
hashCode = hashCode + prime * noDelay.hashCode()
}
if (let Some(linger) <- lingerVal) {
hashCode = hashCode + prime * linger.hashCode()
}
if (let Some(readTimeout) <- readTimeoutVal) {
hashCode = hashCode + prime * readTimeout.hashCode()
}
if (let Some(writeTimeout) <- writeTimeoutVal) {
hashCode = hashCode + prime * writeTimeout.hashCode()
}
hashCode = hashCode + prime * idleTimeoutVal.hashCode()
hashCode = hashCode + prime * bufferAllocateSizeVal.hashCode()
hashCode = hashCode + prime * usePooledBufferAllocatorVal.hashCode()
hashCode = hashCode + prime * maxPooledBuffersVal.hashCode()
hashCode = hashCode + prime * threadPoolNameVal.hashCode()
hashCode = hashCode + prime * threadPoolQueueSizeVal.hashCode()
hashCode = hashCode + prime * maxThreadsVal.hashCode()
hashCode = hashCode + prime * minThreadsVal.hashCode()
hashCode = hashCode + prime * threadIdleTimeoutVal.hashCode()
hashCode = hashCode + prime * useNonExclusiveObjectPoolVal.hashCode()
hashCode = hashCode + prime * objectPoolLifoVal.hashCode()
hashCode = hashCode + prime * testOnCreateVal.hashCode()
hashCode = hashCode + prime * testOnBorrowVal.hashCode()
hashCode = hashCode + prime * testOnReturnVal.hashCode()
hashCode = hashCode + prime * testWhileIdleVal.hashCode()
return hashCode
}
public func checkEquals(other: RedisClientConfigBase): Bool {
if (respVersionVal != other.respVersionVal) {
return false
}
if (userVal != other.userVal) {
return false
}
var myPassword: ?String = None
var otherPassword: ?String = None
if (let Some(password) <- passwordVal) {
myPassword = String.fromUtf8(password)
}
if (let Some(otherPass) <- other.passwordVal) {
otherPassword = String.fromUtf8(otherPass)
}
if (myPassword != otherPassword) {
return false
}
if (clientNameVal != other.clientNameVal) {
return false
}
if (shutdownTimeoutVal != other.shutdownTimeoutVal) {
return false
}
if (waitConnectionTimeoutVal != other.waitConnectionTimeoutVal) {
return false
}
if (checkSubscribeMessageIntervalVal != other.checkSubscribeMessageIntervalVal) {
return false
}
if (asyncWriteVal != other.asyncWriteVal) {
return false
}
if (writeQueueSizeVal != other.writeQueueSizeVal) {
return false
}
if (writeBufferSizeVal != other.writeBufferSizeVal) {
return false
}
if (stickyReadVal != other.stickyReadVal) {
return false
}
if (execOnReadThreadVal != other.execOnReadThreadVal) {
return false
}
if (receiveBufferSizeVal != other.receiveBufferSizeVal) {
return false
}
if (sendBufferSizeVal != other.sendBufferSizeVal) {
return false
}
if (noDelayVal != other.noDelayVal) {
return false
}
if (lingerVal != other.lingerVal) {
return false
}
if (readTimeoutVal != other.readTimeoutVal) {
return false
}
if (writeTimeoutVal != other.writeTimeoutVal) {
return false
}
if (idleTimeoutVal != other.idleTimeoutVal) {
return false
}
if (bufferAllocateSizeVal != other.bufferAllocateSizeVal) {
return false
}
if (usePooledBufferAllocatorVal != other.usePooledBufferAllocatorVal) {
return false
}
if (maxPooledBuffersVal != other.maxPooledBuffersVal) {
return false
}
if (threadPoolNameVal != other.threadPoolNameVal) {
return false
}
if (threadPoolQueueSizeVal != other.threadPoolQueueSizeVal) {
return false
}
if (maxThreadsVal != other.maxThreadsVal) {
return false
}
if (minThreadsVal != other.minThreadsVal) {
return false
}
if (threadIdleTimeoutVal != other.threadIdleTimeoutVal) {
return false
}
if (objectPoolLifoVal != other.objectPoolLifoVal) {
return false
}
if (testOnCreateVal != other.testOnCreateVal) {
return false
}
if (testOnBorrowVal != other.testOnBorrowVal) {
return false
}
if (testOnReturnVal != other.testOnReturnVal) {
return false
}
if (testWhileIdleVal != other.testWhileIdleVal) {
return false
}
if (useNonExclusiveObjectPoolVal != other.useNonExclusiveObjectPoolVal) {
return false
}
return true
}
public func cloneTo(other: RedisClientConfigBase) {
other.respVersion = this.respVersion
other.user = this.user
other.password = this.password
other.clientName = this.clientName
other.shutdownTimeout = this.shutdownTimeout
other.waitConnectionTimeout = this.waitConnectionTimeout
other.checkSubscribeMessageInterval = this.checkSubscribeMessageInterval
other.asyncWrite = this.asyncWrite
other.writeQueueSize = this.writeQueueSize
other.writeBufferSize = this.writeBufferSize
other.stickyRead = this.stickyRead
other.execOnReadThread = this.execOnReadThread
other.receiveBufferSize = this.receiveBufferSize
other.sendBufferSize = this.sendBufferSize
other.noDelay = this.noDelay
other.linger = this.linger
other.readTimeout = this.readTimeout
other.writeTimeout = this.writeTimeout
other.idleTimeout = this.idleTimeout
other.bufferAllocateSize = this.bufferAllocateSize
other.usePooledBufferAllocator = this.usePooledBufferAllocator
other.maxPooledBuffers = this.maxPooledBuffers
other.threadPoolName = this.threadPoolName
other.threadPoolQueueSize = this.threadPoolQueueSize
other.maxThreads = this.maxThreads
other.minThreads = this.minThreads
other.threadIdleTimeout = this.threadIdleTimeout
other.maxSubscriberRecoverDuration = this.maxSubscriberRecoverDuration
other.recoverAttemptsPerMinute = this.recoverAttemptsPerMinute
other.objectPoolLifo = this.objectPoolLifo
other.testOnCreate = this.testOnCreate
other.testOnBorrow = this.testOnBorrow
other.testOnReturn = this.testOnReturn
other.testWhileIdle = this.testWhileIdle
other.useNonExclusiveObjectPool = this.useNonExclusiveObjectPool
}
}
public class RedisClientConfig <: RedisClientConfigBase & Hashable & Equatable<RedisClientConfig> {
private var hostVal: ?String = None
private var portVal: ?UInt16 = None
public mut prop host: ?String {
get() {
return hostVal
}
set(value) {
this.hostVal = value
}
}
public mut prop port: ?UInt16 {
get() {
return portVal
}
set(value) {
this.portVal = value
}
}
public override func configTcpEndpointOptions(endpoint: ClientEndpointConfig) {
super.configTcpEndpointOptions(endpoint)
// Redis连接带认证等状态,所以每个RedisClient只使用一个TCP连接
endpoint.minConnections = 0
endpoint.maxConnections = 1
}
@OverflowWrapping
public open func hashCode(): Int64 {
var hashCode = super.computeHashCode()
let prime = 53
if (let Some(host) <- hostVal) {
hashCode = hashCode + prime * host.hashCode()
}
if (let Some(port) <- portVal) {
hashCode = hashCode + prime * port.hashCode()
}
return hashCode
}
public operator override func ==(other: RedisClientConfig): Bool {
if (hostVal != other.hostVal) {
return false
}
if (portVal != other.portVal) {
return false
}
return super.checkEquals(other)
}
public operator override func !=(other: RedisClientConfig): Bool {
if (hostVal != other.hostVal) {
return true
}
if (portVal != other.portVal) {
return true
}
return !super.checkEquals(other)
}
public func clone(): RedisClientConfig {
let clientConfig = RedisClientConfig()
this.cloneTo(clientConfig)
clientConfig.host = this.host
clientConfig.port = this.port
return clientConfig
}
}