aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/js/backends/websocket.js
blob: 44b260c982ea018b711835309262aa835fb93f41 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
 *  The WebSocket backend is responsible for updating our knowledge of flows and events
 *  from the REST API and live updates delivered via a WebSocket connection.
 *  An alternative backend may use the REST API only to host static instances.
 */
import { fetchApi } from "../utils"

const CMD_RESET = 'reset'

export default class WebsocketBackend {
    constructor(store) {
        this.activeFetches = {}
        this.store = store
        this.connect()
    }

    connect() {
        this.socket = new WebSocket(location.origin.replace('http', 'ws') + '/updates')
        this.socket.addEventListener('open', () => this.onOpen())
        this.socket.addEventListener('close', () => this.onClose())
        this.socket.addEventListener('message', msg => this.onMessage(JSON.parse(msg.data)))
        this.socket.addEventListener('error', error => this.onError(error))
    }

    onOpen() {
        this.fetchData("settings")
        this.fetchData("flows")
        this.fetchData("events")
    }

    fetchData(resource) {
        let queue = []
        this.activeFetches[resource] = queue
        fetchApi(`/${resource}`)
            .then(res => res.json())
            .then(json => {
                // Make sure that we are not superseded yet by the server sending a RESET.
                if (this.activeFetches[resource] === queue)
                    this.receive(resource, json)
            })
    }

    onMessage(msg) {

        if (msg.cmd === CMD_RESET) {
            return this.fetchData(msg.resource)
        }
        if (msg.resource in this.activeFetches) {
            this.activeFetches[msg.resource].push(msg)
        } else {
            let type = `${msg.resource}_${msg.cmd}`.toUpperCase()
            this.store.dispatch({ type, ...msg })
        }
    }

    receive(resource, data) {
        let type = `${resource}_RECEIVE`.toUpperCase()
        this.store.dispatch({ type, cmd: "receive", resource, data })
        let queue = this.activeFetches[resource]
        delete this.activeFetches[resource]
        queue.forEach(msg => this.onMessage(msg))
    }

    onClose() {
        // FIXME
        console.error("onClose", arguments)
    }

    onError() {
        // FIXME
        console.error("onError", arguments)
    }
}
"" return 0 @export @BindToLibGHDL("files_map__location_file_to_pos") def Location_File_To_Pos(Location: LocationType, File: SourceFileEntry) -> int: """ Convert :obj:`Location` and :obj:`File` to a position (offset) into the source file. :param Location: Location :param File: Source file :return: Offset """ return 0 @export @BindToLibGHDL("files_map__location_file_to_line") def Location_File_To_Line(Location: LocationType, File: SourceFileEntry) -> int: """ Convert :obj:`Location` and :obj:`File` to a line number. :param Location: Location :param File: Source file :return: Line number """ return 0 @export @BindToLibGHDL("files_map__location_file_line_to_offset") def Location_File_Line_To_Offset(Location: LocationType, File: SourceFileEntry, Line: int) -> int: """ Get the offset in :obj:`Line` of :obj:`Location`. :param Location: Location :param File: Source file :param Line: Line number :return: Offset """ return 0 @export @BindToLibGHDL("files_map__location_file_line_to_col") def Location_File_Line_To_Col(Location: LocationType, File: SourceFileEntry, Line: int) -> int: """ Get logical column (with HT expanded) from :obj:`Location`, :obj:`File` and :obj:`Line`. :param Location: Location :param File: Source file :param Line: Line number :return: logical column (horizontal tabs are expanded) """ return 0 @export @BindToLibGHDL("files_map__file_to_location") def File_To_Location(File: SourceFileEntry) -> LocationType: """Convert a :obj:`File` into a location. :param File: Source file :return: Location. """ return 0 @export @BindToLibGHDL("files_map__file_pos_to_location") def File_Pos_To_Location(File: SourceFileEntry, Pos: int) -> LocationType: """ Convert a :obj:`File` and an offset :obj:`Pos` in the file into a location. :param File: Source file :param Pos: Offset in the file :return: Location. """ return 0 @export @BindToLibGHDL("files_map__file_line_to_position") def File_Line_To_Position(File: SourceFileEntry, Line: int) -> int: """ Convert a :obj:`File` and :obj:`Line` into a position. :param File: Source file :param Line: Line number :return: Return ``Source_Ptr_Bad`` in case of error (:obj:`Line` out of bounds). """ return 0 @export @BindToLibGHDL("files_map__get_file_name") def Get_File_Name(File: SourceFileEntry) -> NameId: """ Return the name of the file. :param File: Source file to get the filename from. :return: NameId for the filename. """ return 0 @export @BindToLibGHDL("files_map__get_directory_name") def Get_Directory_Name(File: SourceFileEntry) -> NameId: """ Return the directory of the file. :param File: Source file to get the directory name from. :return: NameId for the directory. """ return 0 @export @BindToLibGHDL("files_map__get_file_buffer") def Get_File_Buffer(File: SourceFileEntry) -> bytes: """ Return a buffer (access to the contents of the file) for a file entry. :param File: Source file to get the buffer from. :return: Type: ``File_Buffer_Ptr`` """ return 0 @export @BindToLibGHDL("files_map__get_file_length") def Get_File_Length(File: SourceFileEntry) -> int: """ Get the position of the first EOT character. :param File: Source file :return: Type: ``Source_Ptr`` """ return 0 @export @BindToLibGHDL("files_map__set_file_length") def Set_File_Length(File: SourceFileEntry, Length: int) -> None: """ Set the length of the file (which is less than the size of the file buffer). Set also append two EOT at the end of the file. :param File: Source file :param Length: Length for the file. Type: ``Source_Ptr`` """ return 0 @export @BindToLibGHDL("files_map__get_buffer_length") def Get_Buffer_Length(File: SourceFileEntry) -> int: """ Get the length of the buffer, including the gap and the two EOT. :param File: Source file :return: Type: ``Source_Ptr`` """ @export @BindToLibGHDL("files_map__get_buffer_length") def Get_Buffer_Length(File: SourceFileEntry) -> int: """ Get the length of the buffer, including the gap and the two EOT. :param File: Source file :return: Type: ``Source_Ptr`` """ # @export @BindToLibGHDL("files_map__read_source_file") def Read_Source_File(Directory: NameId, Name: NameId) -> SourceFileEntry: """ Return an entry for a filename. Load the filename if necessary. :param Directory: ``Null_Identifier`` for :obj:`DirectoryId` means current directory. :param Name: File name :return: Return ``No_Source_File_Entry``, if the file does not exist. """ return 0 @export @BindToLibGHDL("files_map__reserve_source_file") def Reserve_Source_File(Directory: NameId, Name: NameId, Length: int) -> SourceFileEntry: """ Reserve an entry, but do not read any file. The length should includes the two terminal EOT. :param Directory: Directory name :param Name: File name :param Length: Length to reserve. Type: ``Source_Ptr`` :return: SourceFile """ return 0 @export @BindToLibGHDL("files_map__discard_source_file") def Discard_Source_File(File: SourceFileEntry) -> None: """ Mark :obj:`File` as unavailable: clear the name and directory. .. hint:: This is needed before creating a new source file with the same name. :param File: Source file to discard. """ @export @BindToLibGHDL("files_map__free_source_file") def Free_Source_File(File: SourceFileEntry) -> None: """ Free resources used by :obj:`File`, but keep the entry. .. note:: It could be recycled for files that could fit - not implemented. :param File: Source file to free. """ @export @BindToLibGHDL("files_map__get_last_source_file_entry") def Get_Last_Source_File_Entry() -> SourceFileEntry: """ Returns the entry of the last known file. .. hint:: This allows creating a table of ``SourceFileEntry``. :return: Last SourceFileEntry. Type: ``SourceFileEntry`` """ return 0