How to retry blocking IO Action when timeout? - haskell

How does one deal with a blocking IO action in Haskell? How can I put this IO action inside a scope and manage this scope from another method? If the timeout is reached, I would just reinvoke this method. Normally in other languages, I would probably put this in a separate thread and abort it if I do not get the result in a configurable time. (The timer being external.)
In my case: I have a number of retries and let's say I want to perform an IO action with a timeout. How can I place the IO action in a timeout-ed scope so that it gets recalled after the timeout expires, if and only if the number of retries is greater 0.
Basically: given our IO action like ioMethod::IO String (I have not looked yet in the socket library for Haskell), we'll assume its a black box,
module Retry where
import IOExternal(ioMethod)
retryFunc :: Int -> IO String
retryFunc retries=do
msg<-retry 5 100 IOExternal
return msg
retry :: Int -> Int -> IOExternal -> IO String
retry retries timeout ioMethod = go retries timeout "" where
go 0 timeout ioMethod msg =
if msg=="" then return "Max Retries reached"
else return msg
go retries timeout ioMethod msg counter
= gogo retries timeout counter msg where
gogo retries timeout 0 msg = return ""
gogo retries timeout counter msg
= ioMethod>>=gogo retries timeout counter-1
I do not know how to model this last condition/line.
P.S I am not yet familiar with threading in Haskell (beginner here) and I do think that the timeout-ed scope should perform in different thread,and somehow I need to check it from my main program, and either recall it (if retries>0) or end the main method.

You can use timeout to add a timeout to any blocking call, and simple recursion for retries:
retry :: Int -> Int -> IO a -> IO (Maybe a)
retry 0 _ _ = return Nothing
retry numRetries microseconds action = do
result <- timeout microseconds action
case result of
Nothing -> retry (numRetries-1) microseconds action
Just a -> return (Just a)
Do read the documentation for caveats about FFI stuff, though.

Related

Yesod WebSocketsT handler cleanup

I'm currently authoring an application in Haskell that relies on Yesod and its web sockets implementation.
I was wondering what is the correct way to acquire and release resources for a WebSocketT handler.
For example, in the following naive case...
chatApp :: WebSocketsT Handler ()
chatApp = do
let outgoingFlow = forever $ deliverOutgoingMessages
let incomingFlow = forever $ deliverIncomingMessages
bracket_ acquireResource
releaseResource
(race_ outgoingFlow incomingFlow)
... releaseResource does not seem to be called when a client disconnects abruptly or purposefully.
This is what I ended up doing over the weekend. This is essentially a replication of how web socket background ping process works, apart for the fact that I'm not swallowing the ping send exception when the other end is no longer reachable, but rather using it to detect the disconnection.
echoApp' :: WebSocketsT Handler ()
echoApp' = do
conn <- ask
let acquire = putStrLn "Acquiring..."
release = putStrLn "Releasing"
hardWork = (threadDelay 600000000)
ping i = do
threadDelay (30 * 1000 * 1000)
WS.sendPing conn (T.pack $ show i)
ping (i + 1)
liftIO $ bracket_ acquire release $ race_ hardWork (ping 1)
The downside of this approach is that there's still an up to 30 seconds window when the web socket process is lingering, but at least the resource gets eventually released in a more or less controllable way.

Undeclared variable error when using mtype with Jspin

I am new to Jspin and Promela. I tried to implement the following system:
A home alarm system can be activated and deactivated using a personal ID key or password, after  activation the system enters a waiting period of about 30 seconds, time that allows users to evacuate the  secured area after which the alarm is armed, also when an intrusion is detected the alarm has a built in waiting period or delay of 15 seconds to allow the intruder to enter the password or swipe the card key thus identifying himself, in case that the identification is not made within the allocated 15 seconds the alarm  will go off and will be on until an id card or password is used to deactivate it.
This is the code:
mtype = {sigact, sigdeact};
chan signal = [0] of {mtype};
/*chan syntax for declaring and initializing message passing channels*/
int count;
bool alarm_off = true; /*The initial state of the alarm is off*/
active proctype alarm()
{
off:
if
:: count >= 30 -> atomic {signal!sigdeact; count = 0;alarm_off = false; goto on;}
:: else -> atomic {count++; alarm_off = true; goto off;}
fi;
on:
if
:: count >=15 -> atomic { signal!sigact; count = 0;
alarm_off = false; goto off;}
:: else -> atomic {signal!sigact; alarm_off = true; goto off;}
fi;
pending:
if
:: count >= 30 -> atomic {count = 0; alarm_off = false; goto on;}
:: count < 30 -> atomic {count++; alarm_off = false; goto pending;}
fi;
}
When I run the code with Jspin I get this message:
Error: undeclared variable: sigact
But I declared this in the header.
How can I solve this?
According to the documentation of Promela, you are using mtype correctly.
In fact, I cannot reproduce your error with spin version 6.4.3, so I suspect this is a specific issue of Jspin not being correctly updated.
Unless you want to use spin instead of Jspin, you can try the following work-around, which should work even with Jspin:
#define sigact 0
#define sigdeact 1
chan signal = [0] of {short}; // or bool for only 2 values
...
Since no one ever reads from signal, I assume the system model is incomplete and that more processes will be added later on.
Be aware that, in the following instruction sequence:
atomic { signal!sigdeact; count = 0; alarm_off = false; goto on; }
the atomicity will be temporarily lost by alarm because signal is a synchronous channel (it has size 0) and so another process has to be immediately scheduled for reading the message being sent.
In off state, when count >= 30 you reset count back to 0, set alarm_off = false and then go to state on. In on state, you immediately set alarm_off back to true. Is this intended? It looks like some mistake, perhaps you meant to go to state pending.
By reading the description of your system, it looks like the alarm is missing some kind of input signal. I suspect you are using the signal channel differently from its intended purpose.
Shouldn't the model have some transition from state pending to off, in case the proper personal ID/password is used?

State Monad with multiple threads

Let's say I have a stateful client smth like
trait Client {
case class S(connection: Connection, failures: Int) // Connection takes 10 seconds to create
def fetchData: State[S, Data] // Takes 10 seconds to fetch
}
I want to make it stateful because the creation of connection is expensive (so I want to cache it) + I have failures count to signal if there are too many failures in a row, then basically recreate connection.
What I've understood from State monad is that effectively it should be calculated on one thread, chaining immutable states sequentially on that thread. I can't afford it in this case, because I fetch operation takes huge amount of time, while all I need is quickly read the state, use the connection from there to start expensive async call. On the other hand, I can't make it State[S, Task[Data]], bacause I need to modify failures in S if the task fetchData fails. So I modified client to be
import fs2.Task
trait Client {
case class S(connection: Connection, failures: Int) // Connection takes 10 seconds to create
def fetchData: StateT[Task, S, Data] // Takes 10 seconds to fetch
}
The thing is I can come up with some Monoid that can add the states irrelevant if what was the initial state. E.g. If I have S1 -> (S2, Data), S1 -> (S3, Data), I could still add S2 and S3 to arrive at the final state regardless of what came before - S2 or S3.
Now I have a kind of Java server (Thrift) that use the handler. I haven't dig into details of how it working precisely yet, but let's assume that it listens for incoming connections and then spawns a thread on which it handles the data retrieval. So in my case I want to block the thread until Task is finished:
class Server(client: Client) {
def handle: Data {
run(client.fetchData)
}
private var state: S = Monoid[S].mempty
private def run(st: State[S, Data]): Data {
val resTask: Task[(S, Data)] = st.run(state)
val (newState, res) = Await.result(resTask.unsafeRunAsyncFuture)
state.synchonized({
state = Monoid[S].mappend(state, newState)
})
res
}
}
My questions are:
1) Am I doing it the right / best way here (my focus is efficiency / no bugs)
2) Do I really need State monad here, or it's better to use ordinary var and work with it?
3) In the examples of State monad I always saw that state is propagated to the top level of the app and handled there. But maybe it's better to handle it on Client level and expose stateless interface to the app?
4) Is this code thread safe, or I should make state some sort of synchronized var? I know that in Objective C this line state = Monoid[S].mappend(state, newState) could crash if in the middle of assignment the state was read from another thread.

Handle "Connection reset by peer" error in haskell's wreq library

I'm making multiple GET requests using Haskell's wreq library. I want to handle connection errors retrying a limited number of times. I thought something like this would work:
getRetried url = retried 0
where maxRetries = 2
retried retries | retries >= maxRetries = throwError $ error "number of retries exceeded"
| otherwise = catchError (get url) (\_ -> (putStrLn "retrying") >> (retried (retries + 1) ) )
but it fails from time to time with the following error:
*** Exception: InternalIOException recv: resource vanished (Connection reset by peer)
What am I missing? Isn't catchError the right way to handle errors?

Specify millisecond-speed of an infinite loop

My main function has one infinite loop and I'd like to execute each loop of it every 100 millisecond. I know it's done by some concurrent or parallel method, but I've never done such things before and have no idea even where to start from. How would you implement such function?
Assuming your loop body takes negligible time, just use threadDelay from Control.Concurrent:
import Control.Concurrent
main = forever $ do
mainBody
threadDelay (100*1000) -- value in microseconds
Update: To account for the time of your loop body, use this:
import Data.Time.Clock
import Control.Concurrent
import Control.Monad
mainBody :: IO ()
mainBody = putStrLn "hi"
main = forever $ do
start <- getCurrentTime
mainBody
end <- getCurrentTime
let diff = diffUTCTime end start
usecs = floor (toRational diff * 1000000) :: Int
delay = 100*1000 - usecs
if delay > 0
then threadDelay delay
else return ()
Haskell's threads are light-weight, so a quick solution would be to fork on each cycle. Thus you'll end up using the main thread as a manager of worker threads, which ensures that a worker gets spawned every 100 micros.
import Control.Concurrent
main =
forever $ do
forkIO $ loopCycle
threadDelay $ 100 * 10^3
In case you care about exceptions not getting lost and getting reraised in the main thread instead, I recommend taking a look at the "slave-thread" package. Actually, I'd recommend to use that package instead of forkIO and brothers by default, but then I'm the author so I might be subjective.
Also note that the above solution might cause an accumulation of worker threads in case the loopCycle will take longer than 100 micros to execute too often. To protect against such a scenario, you can implement a strategy in the manager thread, which will ensure that the number of active workers is limited. Following is how such a strategy could be implemented:
-- From the "SafeSemaphore" package
import qualified Control.Concurrent.SSem as Sem
main =
manager 12 (100 * 10^3) $ putStrLn "Implement me!"
manager :: Int -> Int -> IO () -> IO ()
manager limit delay worker =
do
sem <- Sem.new limit
forever $ do
forkIO $ Sem.withSem sem $ worker
threadDelay delay
You could use sleep to pause the loop at the end of every iteration for 100 milliseconds. https://www.haskell.org/hoogle/?q=sleep

Resources