What does parameters like timeout, connectionTimeout, soTimeout, and infiniteSoTimeout mean in JedisPool? - redis

While defining a jedisPool object, various functions can be chosen from with varying parameters. I want to know what these parameters
timeout
connectionTimeout
soTimeout
infiniteSoTimeout
mean?

Jedis uses java.net.Socket under the hood. The concerned parameters are all directly related to that Socket. Also, the naming of parameters comes mostly from there.
connectionTimeout - timeout value (in milliseconds) to be used while establishing a socket connection.
soTimeout/socketTimeout - timeout value (in milliseconds) to be used while waiting for a response from Redis server (during a regular command execution)
timeout - this is simply a shortcut to use same value for both connectionTimeout and soTimeout
infiniteSoTimeout/blockingSoTimeout - timeout value (in milliseconds) to be used while waiting for a response from Redis server during a blocking command execution. For example, BLPOP is a blocking command.

Related

Timeout in JedisPool definition

While defining a jedisPool object I used the following function and parameters as mentioned here.
public JedisPool(final GenericObjectPoolConfig<Jedis> poolConfig, final String host, int port,
int timeout, final String password, final int database) {
this(poolConfig, host, port, timeout, password, database, null);
}
Everything except for timeout is explanatory. What does timeout stand for?
In the other function definitions, we could find parameters like connectionTimeout, soTimeout, and infiniteSoTimeout. If anyone could direct me to any resources that would be much appreciated. I couldn't find these in the official jedis page.
The single timeout parameter represents same value for both connectionTimeout and soTimeout.
In such case infiniteSoTimeout is defaulted to 0 (zero, representing indefinite time).

Redis RESP3 protocol -- how to set it for luascript?

I am using Redis 7.0.4. I am trying to use RESP3 protocol so that the luascript responses are making more sense. When I use the hello command in luascript, it throws error
This Redis command is not allowed from script
If I set it from command line, it seems to be temporary and fallback to 2.
What is the right way to set it, so my script can take advantage of it?
HELLO is not allowed in Lua script. If you want to switch RESP version in Lua script, you should call redis.setresp(version) instead.
-- use RESP3
redis.setresp(3)
Also, RESP3 support some new types, so you need to be careful with the RESP3 data type conversion from/to Lua types. Check this for detail.

Redis commands synchronous or asynchronous?

AFAIK redis is a single threaded and its uses event loop under the hood. I would want to understand 2 things:
are all redis commands synchronous?
if they are asynchronous
SET mykey "Hello" (first command)
GET mykey (second command)
there is a possibility for the second command to return nil, if the set command isn't executed yet. Is that correct?
Redis is single-threaded , which means all commands should be atomic. For details
In your above example; If the SET command gets to executed first then GET command will wait until SET completion; if GET command gets to executed first then then it will return nil and SET will subsequently be executed. so each command execution is atomic.
refer documentation; https://redis.io/topics/faq.
ps: for redis4.0 there is some multi-threading capability; refer documentation for details

Sponsor's Renewal function stops being called

I have a server and client process both running on the same machine. The client creates a CAO object and uses it for some time (<1s up to hours). It takes a lot of memory so I want to dispose of this object as soon as possible after the client finishes with it.
I set InitialLeaseTime and RenewOnCallTime to 10s (0.1s and 15s have the same problem). I can see that for a few minutes, the sponsor's Renweal functon is being called every 10s. After several minutes the client starts doing different kind of work and the sponsor stops being called (this seems wrong). A few minutes later when the client tries to use the remote object, it throws an exception saying it has been disconnected (probably because the sponsor wasn't called for a long time).
It seems like the lease manager somehow stops trying to check the lease after a while.
Long time in-between responses, but I figure others may run into this issue too, so here goes.
I'd recommend attaching to your server in VS, going to the Debug menu, choosing 'exceptions,' and then checking the 'System.Net.Sockets.SocketException' exception. This will break your program on any socket exception that occurs.
In my case, I've recently begun seeing this issue, and after a lot of debugging noticed that just before the Lease Manager stops checking for leases, a SocketException was occurring. In my case, the socket exception was AddressChangedCallback, with the stack trace:
1 [External Code]
2 System.dll!System.Net.Dns.TryGetAddrInfo(string name = "me.win.mycompany.com", System.Net.AddressInfoHints flags, out System.Net.IPHostEntry hostinfo = null)
3 System.dll!System.Net.Dns.GetAddrInfo(string name)
4 System.dll!System.Net.Dns.InternalGetHostByName(string hostName, bool includeIPv6)
5 System.dll!System.Net.Dns.GetHostEntry(string hostNameOrAddress)
6 System.Runtime.Remoting.dll!System.Runtime.Remoting.Channels.CoreChannel.UpdateCachedIPAddresses()
7 System.Runtime.Remoting.dll!System.Runtime.Remoting.Channels.CoreChannel.OnNetworkAddressChanged(object sender = null, System.EventArgs e = {System.EventArgs})
8 mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
9 mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
10 mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state)
11 System.dll!System.Net.NetworkInformation.NetworkChange.AddressChangeListener.AddressChangedCallback(object stateObject, bool signaled)
12 mscorlib.dll!System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(object state, bool timedOut)
13 [External Code]
This AddressChangedCallback, which, in my case, seems to be related to a network adapter going down or being changed (you can see your network adapters by holding windows+r then typing ncpa.cpl - if you have two or more it's possible this event is caused by you switching between them) appeared to cause the socket to stop reading. This meant that the next time the LeaseManager went to use the remoting connection to check the remote lease, it couldn't read that lease from the dead socket. So, it did the reasonable thing - disconnect that sponsor, since we can't read it anymore, and remove it from the list of sponsors for the object. And since it's probably the only sponsor for the object in question, that object then gets unsponsored by the LeaseManger, leaving it free for the GC to eventually pick up.
One approach to solving this is to, in your InitializeLifetimeService() method, return null instead of setting timeouts. This bypasses the LeaseManager, so you never have to worry about the object getting de-sponsored due to a socket exception, since you're not using leases in the first place. However, if you're like me, this also means you could have a buildup of objects and unmanaged resources over a period of time on the server. The only way around the buildup issue that I can see is making your remoting object implement Dispose, and making sure that you Dispose it when you're finished with it. Basically, you can't rely on the LeaseManager handling garbage collection, so you'll have to do GC yourself, the ol' fashioned way.
Also worthy of note: the ITrackingHandler object will allow you to track when LeaseManager-related objects are Disconnected, Marshaled, and Unmarshaled. It was a big help in figuring out what was going on, since I could see that an object was being disconnected, instead of inferring it from the fact that the calls stopped happening.
I've worked around it by putting the sponsor on the server instead of the client. The server side sponsor seems to be reliably called enough to keep the remote object alive.
Class SelfSponsor
Implements ISponsor
Public Function Renewal(ByVal lease As ILease) As System.TimeSpan Implements ISponsor.Renewal
Return lease.RenewOnCallTime
End Function
End Class
And in the class of the MarshalByRef remote object:
Private Sponsor As SelfSponsor
Public Sub SponsorYourself()
Sponsor = New SelfSponsor
DirectCast(GetLifetimeService(), ILease).Register(Sponsor)
End Sub
Public Sub UnSponsorYourself()
DirectCast(GetLifetimeService(), ILease).Unregister(Sponsor)
End Sub
Somehow the SponsorYourself() code throws an exception if it's placed in the constructor so the client calls SponsorYourself immediately after creating the object.
This would be a bad solution if the server is always running and clients come and go because if a client exits abnormally without explicitly calling UnsponsorYourself() then the object will stay alive forever. But in my case the server is started and stopped by the client so that doesn't matter.

Setting state of a gen_server type application

I am trying to find out whether it is possible to start a gen_server with a given state.
I would like to be able to set up a monitor/supervisor that restarts the server with its last valid state when this server crashes.
Any suggestion on how to tackle this problem would be very Welcome.
So far my only idea is to have a special handle_call/3 that changes the server state to the desired state when called, but I would like to avoid modifying the server module and handle this purely from my monitor/supervisor process if possible.
Thank you for your time.
gen_server:init takes argument Args. You can pass whatever state you want and set it as the state of the server. You can pass Args to start_link and it will pass it to init for you.
http://www.erlang.org/doc/man/gen_server.html#Module:init-1
http://www.erlang.org/doc/man/gen_server.html#start_link-3
I think that in your case you might want to store the state in mnesia. That way you don't have to take care of passing last valid state to the gen_server. In case you don't want to start mnesia you can use ETS. Create public ETS in some process that won't die and use it from your gen_server (note that when server that created ets dies, the ets is destroyed)
http://www.erlang.org/doc/man/ets.html
http://www.erlang.org/doc/man/mnesia.html