many updates
[phd-thesis.git] / top / int.tex
index a1742fc..30e74a2 100644 (file)
@@ -10,7 +10,7 @@
 \begin{chapterabstract}
        This chapter shows the integration of \gls{MTASK} with \gls{ITASK} by showing:
        \begin{itemize}
-               \item an architectural overview of \gls{MTASK};
+               \item an architectural overview \gls{MTASK} applications;
                \item on the interface for connecting devices;
                \item the interface for lifting \gls{MTASK} tasks to \gls{ITASK} tasks;
                \item and interface for lifting \gls{ITASK} \glspl{SDS} to \gls{MTASK} \glspl{SDS}.
@@ -20,7 +20,7 @@
 The \gls{MTASK} language is a multi-view \gls{DSL}, i.e.\ there are multiple interpretations possible for a single \gls{MTASK} term.
 Using the byte code compiler (\cleaninline{BCInterpret}) \gls{DSL} interpretation, \gls{MTASK} tasks can be fully integrated in \gls{ITASK}.
 They are executed as if they are regular \gls{ITASK} tasks and they communicate may access \glspl{SDS} from \gls{ITASK} as well.
-\Gls{MTASK} devices contain a domain-specific \gls{OS} (\gls{RTS}) and are little \gls{TOP} engines in their own respect, being able to execute tasks.
+\Gls{MTASK} devices contain a domain-specific \gls{OS} and are little \gls{TOP} engines in their own respect, being able to execute tasks.
 \Cref{fig:mtask_integration} shows the architectural layout of a typical \gls{IOT} system created with \gls{ITASK} and \gls{MTASK}.
 The entire system is written as a single \gls{CLEAN} specification where multiple tasks are executed at the same time.
 Tasks can access \glspl{SDS} according to many-to-many communication and multiple clients can work on the same task.
@@ -35,15 +35,15 @@ Using \cleaninline{liftmTask}, \gls{MTASK} tasks are lifted to a device (see \cr
        \label{fig:mtask_integration}
 \end{figure}
 
-\section{Devices}\label{sec:withdevice}
+\section{Connecting edge devices}\label{sec:withdevice}
 When interpreted by the byte code compiler view, an \gls{MTASK} task produces a compiler.
 This compiler is exceuted at run time so that the resulting byte code can be sent to an edge device.
 All communication with this device happens through a so-called \emph{channels} \gls{SDS}.
 The channels contain three fields, a queue of messages that are received, a queue of messages to send and a stop flag.
 Every communication method that implements the \cleaninline{channelSync} class can provide the communication with an \gls{MTASK} device.
-As of now, serial port communication, direct \gls{TCP} communication and \gls{MQTT} over \gls{TCP} are supported as communication providers.
-The \cleaninline{withDevice} function transforms a communication provider and a task that does something with this device to an \gls{ITASK} task.
-Internally, the task sets up the communication, exchanges specifications, executes the inner task while handling errors, and finally cleans up after closing.
+As of now, serial port communication, direct \gls{TCP} communication and \gls{MQTT} over \gls{TCP} are supported as communication providers (see \cref{lst:connection_types}).
+The \cleaninline{withDevice} function transforms such a communication provider and a task that does something with this device to an \gls{ITASK} task.
+Internally, the task sets up the communication, exchanges specifications with the device, executes the inner task while handling errors, and finally cleans up after closing.
 \Cref{lst:mtask_device} shows the types and interface to connecting devices.
 
 \begin{lstClean}[label={lst:mtask_device},caption={Device communication interface in \gls{MTASK}.}]
@@ -52,10 +52,48 @@ Internally, the task sets up the communication, exchanges specifications, execut
 
 class channelSync a :: a (Shared sds Channels) -> Task () | RWShared sds
 
-withDevice :: a (MTDevice -> Task b) -> Task b | iTask b & channelSync, iTask a
+withDevice :: a (MTDevice -> Task b)
+       -> Task b | iTask b & channelSync, iTask a
 \end{lstClean}
 
-\section{Lifting tasks}\label{sec:liftmtask}
+\subsection{Implementation}
+The \cleaninline{MTDevice} abstract type is internally represented as three \gls{ITASK} \gls{SDS} that contain all the current information about the tasks.
+The first \gls{SDS} is the information about the \gls{RTS} of the device, i.e.\ metadata on the tasks that are executing, the hardware specification and capabilities, and a list of fresh task identifiers.
+The second \gls{SDS} is a map storing downstream \gls{SDS} updates.
+When a lifted \gls{SDS} is updated on the device, a message is sent to the server.
+This message is initially queued in the map to allow for asynchronous handling of multiple updates.
+Finally, the \cleaninline{MTDevices} type contains the communication channels.
+
+The \cleaninline{withDevice} task itself first constructs the \glspl{SDS} using the \gls{ITASK} function \cleaninline{withShared} to create anonymous local \glspl{SDS}.
+Then, it performs the following four tasks in parallel to monitor the edge device.
+\begin{enumerate}
+       \item It synchronises the channels using the \cleaninline{channelSync} overloaded function.
+               Errors that occur here are converted to the proper \gls{MTASK} exception.
+       \item Watches the channels for the shutdown flag.
+               If the connection is lost with the device unexpectedly, an \gls{MTASK} exception is thrown.
+       \item Watches the channels for messages and processes them accordingly by changing the device information \gls{SDS} or adding the lifted \gls{SDS} updates to the corresponding \gls{SDS} update queue.
+       \item Sends a request for a specification. Once the specification is received, the device task is run.
+               The task value of this device task is then used as the task value of the \cleaninline{withDevice} task.
+\end{enumerate}
+
+If at any stage an unrecoverable device error occurs, an \gls{ITASK} exception is thrown on the \cleaninline{withDevice} task.
+This exception can be caught in order to device some kind of fail-safe mechanism.
+For example, when a device fails, the tasks can be sent to another device.
+\todo[inline]{Example of failsafe?}
+
+%withDevice spec deviceTask
+%      withShared newMap \sdsupdates->
+%      withShared ([], [MTTSpecRequest], False) \channels->
+%      withShared default \dev->parallel
+%              [ channelSync spec // unexpected disconnect
+%              , watchForShutdown // unexpected disconnect
+%              , watchChannels    // process messages
+%              , waitForSpecification
+%                      >>| deviceTask
+%                      >>* [ifStable: issueShutdown]
+%              ]
+
+\section{Lifting \texorpdfstring{\gls{MTASK}}{mTask} tasks}\label{sec:liftmtask}
 Once the connection with the device is established, \gls{MTASK} tasks can be lifted to \gls{MTASK} tasks using the \cleaninline{liftmTask} family of functions (see \cref{lst:liftmtask}).
 Given an \gls{MTASK} task in the \cleaninline{BCInterpret} view and a device obtained from \cleaninline{withDevice}, an \gls{ITASK} task is returned.
 This \gls{ITASK} task tethers the \gls{MTASK} task that is executed on the microcontroller.
@@ -65,18 +103,59 @@ Hence, when for example observing the task value, the actual task value from the
 liftmTask :: (Main (MTask BCInterpret u)) MTDevice -> Task u | iTask u
 \end{lstClean}
 
-Under the hood, \cleaninline{liftmTask} compiler the \gls{MTASK} task to byte code, gathers the initial values for the lifted \glspl{SDS} and sends the data to the device.
-Once acknowledged, the \gls{MTASK} task value and the \glspl{SDS} are monitored.
-If the \gls{ITASK} server updates the value of a lifted \gls{SDS}, the appropriate message is sent to the \gls{MTASK} to notify it of the change.
-Furthermore, the \gls{MTASK} device may update the \gls{SDS}, and in that case the message is picked up by the \cleaninline{liftmTask} task and the \gls{SDS} on the \gls{ITASK} server updated accordingly.
+Under the hood, \cleaninline{liftmTask}:
+\begin{itemize}
+       \item Generates a fresh task identifier for the device.
+       \item Compiles the task and fetches the values for the tethered \glspl{SDS}.
+       \item Sends the task to the device
+       \item Watches, in parallel: the tethered \glspl{SDS} in \gls{ITASK}, if they are updated, a message is sent to the device; the \gls{SDS} update queue, if there is a downstream update, the \gls{ITASK} \gls{SDS} it references is updated as well; and the task value.
+\end{itemize}
+
+The task value of the \cleaninline{liftmTask} task is the task value of the task on the edge device.
+
+\section{Lifting \texorpdfstring{\gls{ITASK}}{iTask} \texorpdfstring{\glsxtrlongpl{SDS}}{shared data sources}}\label{sec:liftsds}
+Lifting \gls{ITASK} \glspl{SDS} to \gls{MTASK} \glspl{SDS} is something that mostly happens at the compiler level using the \cleaninline{liftsds} function (see \cref{lst:mtask_itasksds}).
+\Glspl{SDS} in \gls{MTASK} must always have an initial value.
+For regular \gls{SDS} this value is given in the source code, for lifted \gls{ITASK} \glspl{SDS} this value is obtained by reading the values once just before sending the task to the edge device.
+On the device itself, there is just one difference between lifted \glspl{SDS} and regular \glspl{SDS}: after changing \pgls{SDS}, a message is sent to the server containing this new value.
+The \cleaninline{withDevice} task (see \cref{sec:withdevice}) receives and processes this message by writing to the \gls{ITASK} \gls{SDS}.
+Tasks watching this \gls{SDS} get notified then through the normal notification mechanism of \gls{ITASK}.
 
-\section{Lifting \texorpdfstring{\glsxtrlongpl{SDS}}{shared data sources}}\label{sec:liftsds}
 \begin{lstClean}[label={lst:mtask_itasksds},caption={Lifted \gls{ITASK} \glspl{SDS} in \gls{MTASK}.}]
 class liftsds v where
        liftsds :: ((v (Sds t)) -> In (Shared sds t) (Main (MTask v u)))
                -> Main (MTask v u) | RWShared sds
 \end{lstClean}
 
+The compilation of the code and the serialisation of the data throws away all typing information.
+\Cref{lst:mtask_itasksds_lens} shows a pseudocode implementation of \cleaninline{liftsds}.
+\Glspl{SDS} are stored in the compiler state as a map from identifiers to either an initial value or an \cleaninline{MTLens}.
+The \cleaninline{MTLens} is a type synonym for a \gls{SDS} that represents the typeless serialised value of the underlying \gls{SDS}.
+Such a \gls{SDS} is created by using the \cleaninline{mapReadWriteError} which, given a pair of read and write functions with error handling, produces a \gls{SDS} with the lens embedded.
+The read function transforms, the function that converts a typed value to a typeless serialised value, just applies the serialisation.
+The write function, the function that, given the new serialised value and the old typed value, produces a new typed value tries do deserialise the value.
+
+First, in similar fashion to how functions are implemented, using fixed points, the \glspl{SDS} is 
+
+% VimTeX: SynIgnore on
+\begin{lstClean}[label={lst:mtask_itasksds_lens},caption={Lens applied to lifted \gls{ITASK} \glspl{SDS} in \gls{MTASK}.}]
+instance liftsds BCInterpret where
+       liftsds def = {main =
+                       let (t In e) = def (abort "liftsds: expression too strict")
+                       in addSdsIfNotExist (Right $ lens t)
+                               >>= \sdsi-> let (t In e) = def (pure (Sds sdsi))
+                                       in e.main
+               }
+       where
+               lens :: ((Shared sds a) -> MTLens) | type, iTask a & RWShared sds
+               lens = mapReadWriteError
+               ( \r->Ok (fromString (toByteCode{|*|} r)
+                       , \w r-> ?Just <$> iTasksDecode (toString w)
+                       ) ?None
+\end{lstClean}
+% VimTeX: SynIgnore off
+
+
 \section{Conclusion}