heisenware / vrpc-js Goto Github PK
View Code? Open in Web Editor NEWAsynchronous RPC via MQTT for Javascript
Home Page: https://vrpc.io
License: MIT License
Asynchronous RPC via MQTT for Javascript
Home Page: https://vrpc.io
License: MIT License
Is your feature request related to a problem? Please describe.
VRPC allows multiple clients to act on a single agent. Depending on the agent's code such client calls may or may not change the agent's state. In case a state-changing call (mutation) occurred, it affects the result of subsequent calls from other clients. Hence, the agent acts like a shared resource to all clients when talking about state-changing (mutating) events. While this is appropriate for some use-cases it may not for others. In case clients should be able to mutate the state of the agent but yet act logically completely isolated to other clients this can naturally be realized using VRPC's OOP support and dedicating an instance on the agent to a specific client. This is the way VRPC realizes a multi-tenancy scenario and can implement all use-cases.
With this concept in mind, a client's create
call should provide an option isIsolated
that when set to true
will hide the instance from the public auto-discovery and bind its life time to the one of the client. Such behavior should not (as implemented today) implicitly change by providing or not an explicit name to the to-be-created instance. Client or agent side instance name generation must be treated as a different concern (that should still be available) that must well be separated from the tenancy concept described above.
Describe the solution you'd like
Additional option 'isIsolated' on client create
function.
Describe the Bug
Since version 2.3.0, the domain
property must be specified in the VrpcRemote constructor and it can not anymore be a wildcard. In other words: a single client may only work with agents within a specific domain, not across domains.
This (design-)decision simplifies the underlying code and many other API calls which still - and inconsistently - allow for an explicit domain option. Consequently, the code should be simplified, the API and the documentation adapted.
When following the instructions for testing the examples, one is asked to register an account at https://vrpc.io/app , but the page is empty: "here is nothing, not even a 404"
It's not Bielefeld, but hey...
Describe the Bug
If you have one instance of VrpcLocal and then create another. Callbacks on the classes created from the first instance will stop working.
Steps To Reproduce
Steps to reproduce the behavior:
Applying the diff attached makes the tests to start to fail.
Expected Behavior
Callback should keep working after several instanciations
vrpcLocalDiff.txt
Is your feature request related to a problem? Please describe.
When VRPC is used to embed C/C++ libraries to be called by e.g. a local Node.js client and the embedded C++ functions are of synchronous (blocking) nature, users typically encounter a problem. Those function calls when executed by the (local) VRPC client will block the main thread and hence - in Node.js - the main event-loop. This is a performance killer for the rest of the client application. Today, users must workaround themselves by wrapping those calls into threads which ship their data back onto the clients' application event-loop (libuv in case of Node.js).
Describe the solution you'd like
VRPC should provide a simple option that - when enabled - automatically executes (selected or all?) functions asynchronously, obsoleting the need for the user to implement any additional threading code. Function that are bound this way should automatically manifest themselves as asynchronous functions (i.e. return a Promise
) on the client as well and be executable with a simple await
statement.
Describe alternatives you've considered
An alternative could be to use potentially available threading features of the client application on such functions.
Additional context
Most certainly such an enhancement must be done in the addon.cpp
(Node.js) and module.cpp
(Python3) files. The underlying technology should make use of a second event-loop - using the same technology as already implemented on the stand-alone C++ agents (i.e. asio
and friends)
Is your feature request related to a problem? Please describe.
Currently, all examples are formulated as markdown documents only. In order to ensure that all examples are always working as described, the actual code should be added to the repository and the example should be installed and tested to best extend as part of the regular test runs.
Describe the solution you'd like
Move the markdowns out of the docs
folder into and create a folder for each one under the examples
directory. The old markdown should then simply read README.md
and a install.sh
should be added for generic installation as used during the testing.
Describe the Bug
If a client application uses VrpcRemote to register event listeners to remote objects and does so for a larger number of objects, the seemingly "random" proxyId
(consisting of 2 bytes) is by far not random enough to prevent collisions. The erroneous behaviour is that event data is passed into the wrong callbacks.
In fact, in the Cybus project we easily run into the situation where so many proxy objects have been created that some of them use the same proxyId
. When we then register for the state
event of each of that object, we easily end up in a situation where the listener callback for one object's state erroneously receives the actual arguments intended for a different object's state. That means the vrpc callback mechanism for event notification is not reliable enough.
Steps To Reproduce
Steps to reproduce the behavior:
state
eventstate
event remotely using a VrpcRemote object: proxy.on('state',(state) => console.log('got state')
but also keep track which object receives which state message (will require a slightly longer code example than this one-liner)Expected Behavior
The on('eventName', ...)
registration should let the callback be triggered only on events by the intended remote object, not any others.
Desktop (please complete the following information):
Additional context
The problem is caused by the combination of the following factors:
proxyId
is not very random because it consists only of 2 bytes https://github.com/heisenware/vrpc/blob/master/vrpc/VrpcRemote.js#L910id
adds the event name, but this can easily be constant (such as 'state'
) over many many objects https://github.com/heisenware/vrpc/blob/master/vrpc/VrpcRemote.js#L1056We strongly suggest adding a collision check before using a newly generated proxyId
, so that a newly created random identifier which is supposed to be locally unique should really be verified to be unique. Hence, in addition to this._cachedSubscriptions
, there should probably be also something like a Set of this._cachedProxyId
where each newly created proxyId should be marked as being used, until it is cleaned up again.
Note that simply creating longer proxyIds might make the problem smaller but will for sure not solve it completely. The only complete solution is to add a collision check in the creation of the proxyId
.
Describe the Bug
In the Cybus software we were dealing with a vrpc-wrapped C++ extension where we called some method from javascript into C++, but were passing a callback to that method, which then is called from the C++ side once it is finished. As things go, our supplied callback method was unexpectedly throwing an exception.
However, the VrpcLocal location that calls our callback doesn't guard this function call by try-catch, causing the whole process to segfault!
{"level":30,"time":1635256410381,"pid":11,"hostname":"protocol-mapper","service":"protocol-mapper","id":"focasmachineservice-focasConnection","className":"FocasConnection","msg":"Connected FocasConnection"}
/snapshot/app/src/protocols/focas/stack/node_modules/vrpc/vrpc/VrpcLocal.js:233
value.apply(null, args) // This is the actual function call
TypeError: Cannot read property 'id' of undefined
at callback (/snapshot/app/src/protocols/focas/FocasConnection.js)
at EventEmitter.<anonymous> (/snapshot/app/src/protocols/focas/stack/node_modules/vrpc/vrpc/VrpcLocal.js:233:17)
at Object.onceWrapper (events.js:422:26)
at EventEmitter.emit (events.js:315:20)
at /snapshot/app/src/protocols/focas/stack/node_modules/vrpc/vrpc/VrpcLocal.js:63:26
(In that case, we had some stupid typo which caused the TypeError exception, but the main point is that any exception could appear in such a callback.)
Our request is whether VrpcLocal.js line 233 could guard the apply
function call with try-catch, so that an exception in the called function is caught, gets an error logged, and life goes on. (vrpc version 2.6.0.)
@bheisen Are you open for such a try-catch around the apply
in VrpcLocal?
Describe the Bug
When using vrpc to wrap a C++ class into a nodejs addon, this will fail to compile (and work) if the C++ class is "non-copyable", i.e. its copy constructor is deleted. I encountered this while trying to wrap a C++ class that was using some thread and mutex members which are non-copyable.
Steps To Reproduce
In the file examples/Bar.hpp
, add a deleted copy constructor in the class declaration, i.e. a line saying
Bar(const Bar&) = delete;
Then build the project by calling npm run build
. Resulting compile error is this:
In file included from ../vrpc/addon.cpp:42:
../vrpc/vrpc.hpp: In instantiation of 'vrpc::Value::holder::holder(const T&) [with T = vrpc_example::Bar]':
../vrpc/vrpc.hpp:501:15: required from 'vrpc::Value::Value(const T&) [with T = vrpc_example::Bar]'
../vrpc/vrpc.hpp:445:21: required from 'std::string vrpc::to_string(const T&) [with T = vrpc_example::Bar; std::string = std::__cxx11::basic_string]'
../vrpc/vrpc.hpp:691:31: required from 'std::string vrpc::Value::holder<std::shared_ptr<_Tp> >::format() const [with T = vrpc_example::Bar; std::string = std::__cxx11::basic_string]'
../vrpc/vrpc.hpp:690:27: required from here
../vrpc/vrpc.hpp:643:14: error: use of deleted function 'vrpc_example::Bar::Bar(const vrpc_example::Bar&)'
643 | : held(new T(value)) { }
| ^~~~~~~~~~~~
In file included from ../examples/binding.cpp:2,
from ../vrpc/addon.cpp:45:
../examples/Bar.hpp:25:5: note: declared here
25 | Bar(const Bar&) = delete;
| ^~~
make: *** [vrpc_example.target.mk:109: Release/obj.target/vrpc_example/vrpc/addon.o] Error 1
make: Leaving directory '/home/cs/org/vrpc/build'
Expected Behavior
It is expected to be able to wrap a non-copyale C++ class, too. The compiler instantiation stack seems to indicate that the copy constructor was instantiated "only" for the to_string
function and this seems unnecessary to me. The stack seems to indicate that the value object was wrapped in a shared_ptr anyway (line vrpc.hpp:691), but then from to_string
the copy constructor of Value
is called directly (line vrpc.hpp:445), which on the other hand seems rather weird to me. Maybe you need to do some tricks in to_string
so that no copy constructor of Value
is called?
Version
Current git master, i.e. version 2.2.3.
Describe the Bug
The callback on the mqttClient.subscribe() call receives an argument granted
. This array must be checked for each topic's qos
value, because this might be value 128 saying that this topic subscribe has failed (Reference: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718071 SUBACK packet payload format, “Allowed return code: 0x80 Failure”). This must be checked for explicitly, but currently isn’t done.
Steps To Reproduce
Steps to reproduce the behavior:
Function call "...()" timed out (> 6000 ms)
Expected Behavior
If the MQTT subscription fails, there must be a clear error event from the VrpcAgent and VrpcClient objects so that the application code can decide what to do, such as restarting the whole Vrpc connection or such.
Is your feature request related to a problem? Please describe.
This feature is useful when working in a fully distributed system in which the client should not care where instances are located but still trigger calls relevant for all instances of a specific class.
Describe the solution you'd like
The client code should check the agent
option when receiving a request to callAll
. If no agent is specified and no default is set (i.e. agent = '*'
) the remote call should loop over all existing agents and trigger the corresponding request.
Additional context
The feature will render especially useful for react-vrpc
. Users using a backend
that solely specifies a class but no agent will benefit from being able to synchronize an entire set of distributed instances across any number of agents.
In vrpc/VrpcRemote.js:169, if oldInstances
is undefined (occurred here because of mqtt messages that came from a different client), the call oldInstances.filter()
will crash.
Please insert another guard in line 168, if oldClassInfo.instances
is undefined but oldClassInfo
was defined.
Is your feature request related to a problem? Please describe.
When working in browser context it can be quite helpful to distinguish the different RPC requests triggered by user interaction. Most of the time we will have a proxy
object in hand and hence it would be extremely useful to be able to access the information directly from there.
Describe the solution you'd like
Injecting the public variables:
vrpcClientId
vrpcInstanceId
vrpcProxyId
into the proxy instance.
Describe alternatives you've considered
Alternatively or better additionally the VRPC remote client could provide a public getter function for the vrpcClientId.
Additional context
The addition of the before mentioned properties should reflect non-breaking changes and could be simply added.
I saw this this library useful for my project. i checked out the examples and didn't see any mqtt configuration on the client side,
i'm wondering is it possible to utilize this library to on-prem server and with custom mqtt config, or is it licensed or something?
Describe the Bug
In vrpc/VrpcAdapter.js, Line 109 in the function VrpcAdapter.register( ) a register
call is made with some variable arguments. However, when including vrpc in a front-end app (e.g. a React app) and letting this being packed by webpack, the webpack tool complaints loudly about this dynamic require
. This complaint is because webpack surely doesn't know which files need to be bundled and sent to the browser.
Actually this causes webpack v5 to go to every single file trying to setup modules for it before checking which ones are actually being used. Some of those files are not in javascript (some are in python, some in cpp, there are LICENSE files and bash files that execute javascript). A side-effect symptom is that the loading time of the React app are now on the order of ~30 seconds.
This has been the case since approx. October and react-scrips also mentioned that as a warning since then.
Steps To Reproduce
Steps to reproduce the behavior:
./node_modules/vrpc/vrpc/VrpcAdapter.js
Critical dependency: the request of a dependency is an expression
Expected Behavior
There shouldn't be such a warning. And the webpack tool shouldn't encounter a dynamic require
call.
Ideally that whole VrpcAdapter.register() feature needs to be separated into some other file which is not loaded at all when using vrpc from such a react-app, like "VrpcAdapterRegistration.js" or something like that.
Our frontend colleague suspects that any frontend app will encounter this issue and will want to avoid dealing with the dynamic require calls.
Describe the Bug
The current ci involves the production vrpc.io broker for testing. Authorization is granted through a special access token which is configured as a secret env var in travis-ci. While this works for internal PRs it won't (for travis-ci security reasons) for external PRs keeping all those tests failing all the time.
Steps To Reproduce
Fork the repository, and file a PR using changed code on that fork.
Expected Behavior
Contributors should be able to run tests locally and remotely as triggered through the ci pipeline.
Additional context
Idea for a solution: only test against the production vrpc.io broker when the VRPC_TEST_TOKEN
env is defined. If not use a docker-compose based strategy an bring up a local containerized broker.
Describe the Bug
When providing a wrong broker url or when authentication on a valid broker url is denied no events are fired and the applications hangs on an never resolving promise in the agent.serve()
function.
Steps To Reproduce
Entering non-existing broker url or have a broker denying access will lead to this scenario.
Expected Behavior
An 'error' event should be triggered after some timeout time. Or in other words - as the agent is forwarding the events from
mqttjs - the there-documented behavior is expected.
Used Programming Language
Node.js
Is your feature request related to a problem? Please describe.
In case we want to use smart phones as competent IoT devices (camera, gps, microphone, gyroscope, etc.) we should be able to register those as agent. The easiest way to do that is to provide a PWA that runs the agent. For that we need to register javascript that executes in the browser.
Describe the solution you'd like
We need to wepack the apdater and agent portion as well.
Describe the Bug
Our project "profinet-stack" runs into a C++ compile error with vrpc-2.4.0 but was compiling fine with vrpc-2.3.2.
Steps To Reproduce
npm install
addon.cpp
in connection with vrpc.hpp
Expected Behavior
C++ compile with vrpc 2.4.0 should work just as it did with vrpc 2.3.2.
Error message
The compiler prints a lot of errors; the first one is this:
make: Entering directory '/home/foo/example-stack/build'
CXX(target) Release/obj.target/cybus_profinet/node_modules/vrpc/vrpc/addon.o
In file included from ../node_modules/vrpc/vrpc/addon.cpp:46:
../node_modules/vrpc/vrpc/vrpc.hpp:1479:34: error: 'Ret' was not declared in this scope
1479 | _VRPC_MEMBER_FUNCTION_3(Klass, Ret, Function)
| ^~~
../node_modules/vrpc/vrpc/vrpc.hpp:1422:35: note: in definition of macro 'VRPC_MEMBER_FUNCTION_3'
1422 | Klass, decltype(static_cast<Ret (Klass::*)()>(&Klass::Function)),
| ^~~
../node_modules/vrpc/vrpc/vrpc.hpp:1278:19: note: in expansion of macro 'VRPC_VOID_MEMBER_FUNCTION_2'
1278 | #define CAT(A, B) A##B
| ^
../node_modules/vrpc/vrpc/vrpc.hpp:1279:27: note: in expansion of macro 'CAT'
1279 | #define SELECT(NAME, NUM) CAT(##NAME##, NUM)
| ^~~
../node_modules/vrpc/vrpc/vrpc.hpp:1287:30: note: in expansion of macro 'SELECT'
1287 | #define VA_SELECT(NAME, ...) SELECT(NAME, VA_SIZE(VA_ARGS))(VA_ARGS)
| ^~~~~~
../node_modules/vrpc/vrpc/vrpc.hpp:1305:3: note: in expansion of macro 'VA_SELECT'
1305 | VA_SELECT(VRPC_VOID_MEMBER_FUNCTION, VA_ARGS)
| ^~~~~~~~~
../cpp/binding.cpp:53:3: note: in expansion of macro 'VRPC_VOID_MEMBER_FUNCTION'
53 | VRPC_VOID_MEMBER_FUNCTION(ProfinetSniffer,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
Desktop (please complete the following information):
Describe the Bug
When using many agents with several classes, the attaching to instance stops to work reliably. In consequence, timeout errors are thrown by the Node.js client.
Steps To Reproduce
Instantiate many agents and see VRPC Live failing to attach to just created instances.
Expected Behavior
Attaching should always work.
Additional context
The issue seem to be related to the way the local cache is inspected to find instances that are asked for
Environment:
Minimal sample
# on the remote site
class Test {
static async myFunc () {
return 'foobar'
}
}
VrpcAdapter.register(Test)
...
# on the local site
const result = await vrpcRemote.callStatic({
className: 'Test',
functionName: 'myFunc'
})
console.log(result)
This will not output foobar
(as expected), but a string similar to __p__myFunc-0
which is obviously the internal call id of the promise.
Reading through the code it appears that promise handling for static functions is just not implemented yet. The same works perfectly for regular instance member functions.
Is your feature request related to a problem? Please describe.
When the VrpcAgent object starts the MQTT connection, it also sets a MQTT client ID. This client ID is generated in the VrpcAgent.js code but cannot be set from the application code. Sometimes the application needs to set the MQTT client ID into some controlled string before the MQTT connection is established, so it should be possible to set this.
Describe the solution you'd like
Add an optional mqttClientId
argument to VrpcAgent.serve(), or as option into the constructor.
Related: In VrpcClient
there also isn't an argument or option, but the mqtt client id is set in the constructor as member variable this._mqttClientId
already, so the application code can just modify that member variable before calling connect
. Not particularly elegant, but works already.
Ich hab mal wieder einen crash in Vrpc produziert: Wenn im remote agent eine callback-Funktion implementiere, die keine Argumente bekommt, ist im MQTT protocol die property data:null. Das ergibt in VrpcRemote.js:729 ein bamm:
/app/node_modules/vrpc/vrpc/VrpcRemote.js:729
const args = Object.keys(data).sort()
^
TypeError: Cannot convert undefined or null to object
Abhilfe: const args = data ? Object.keys(data)...... : null
Problem
The current dependency of npm package mqtt
4.2.4 contains a problem that will occasionally break when receiving mqtt messages longer than 255 bytes, showing a "Error: Invalid length" exception. The actual issue is contained in the sub-dependency mqtt-packet
, where version 6.6.0 is affected.
Details
Of mqtt-packet
, the previous version 6.5.0 and lower are not affected, 6.6.0 is affected, and any version higher (i.e. 6.6.1 or higher) will not be affected anymore. See issue mqttjs/mqtt-packet#95 and resolving PR mqttjs/mqtt-packet#96
Hence, mqtt
4.2.2 and lower is not affected, but 4.2.3 through 4.2.6 are affected. There is not yet a version available which is not affected anymore.
Course of action
Please downgrade to mqtt 4.2.2. Once a newer mqtt with the resolution is available, this needs to be updated again.
Is your feature request related to a problem? Please describe.
Currently, only agents themselves can unregister from the broker (by deleting the persitsted agent and class info messages).
This is not sufficient when working on a system where agents are not under direct control as it will get polluted with old agents and no easy way to delete the agents known to never be online again.
Describe the solution you'd like
The remote client should have a function unregisterAgent
which allows for removing the persisted information of an offline agent.
With most recent nodejs, addon.cpp does not any longer compile:
../node_modules/vrpc/vrpc/addon.cpp:224:39: error: no matching function for call to 'v8::Function::Call(v8::Local<v8::Primitive>, const unsigned int&, v8::Local<v8::Value> [1])'
224 | cb->Call(Null(isolate), argc, argv);
| ^
In file included from /home/cs/.cache/node-gyp/12.13.1/include/node/node.h:63,
from ../node_modules/vrpc/vrpc/addon.cpp:39:
/home/cs/.cache/node-gyp/12.13.1/include/node/v8.h:4193:43: note: candidate: 'v8::MaybeLocal<v8::Value> v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*)'
4193 | V8_WARN_UNUSED_RESULT MaybeLocal<Value> Call(Local<Context> context,
| ^~~~
/home/cs/.cache/node-gyp/12.13.1/include/node/v8.h:4193:43: note: candidate expects 4 arguments, 3 provided
The code in addon.cpp line 224 needs to be adapted to pass a Local as first argument, otherwise vrpc addons cannot be compiled with most recent nodejs. Thanks!
The vrpc topic structure is occasionally being changed, last time e.g. between vrpc version 2.1.0-alpha.0
and 2.1.0-alpha.1
IIRC. This means that e.g. an Agent of version 2.1.0-alpha.0 and a server with Remote of version 2.1.1 cannot communicate with each other, even though both can correctly authenticate at the MQTT broker and no error is shown there, which makes the cause for the communication failure hard to detect. This ticket asks to introduce some extra checks on the server side whether an agent of an older protocol version tries to communicate here, to avoid these hard-to-detect situation.
Written as a user story: As a service technician who updates the server software instance to vrpc-2.1.1, but forgets to update the remote agent instance from 2.1.0-alpha.0 to some newer version, I want to see a helpful error message on either the server or the agent side stating that a connection attempt from another vrpc instance has been detected but is using an incompatible version of the vrpc protocol. The error message should preferrably be on the server side (new software), but could alternatively also appear in the agent (old software), as long as at least one message appears somewhere.
It has been observed, that creating many (> 100) remote instances of objects with VRPC takes much longer than expected. We have measured latencies of around 400-800ms per instance in a test setup. By looking through the code and the timings, the following performance improvement points have been identified:
With that, the latency problems of 800ms can be reduced to <15ms.
The documentation of the events emitted by the VrpcRemote seems to:
The events are mentioned below are connected, connect, reconnect, close, offline, end, instanceNew, instanceGone and error.
const remote = new VrpcRemote({
broker: `wss:${window.location.host}/mqtt`,
domain: 'internal.cybus',
bestEffort: true,
username,
password
})
console.group('Setting up listeners')
remote.on('connected', () => console.log('Event fired: connected'))
remote.on('connect', () => console.log('Event fired: connect'))
remote.on('reconnect', () => console.log('Event fired: reconnect'))
remote.on('close', () => console.log('Event fired: close'))
remote.on('offline', () => console.log('Event fired: offline'))
remote.on('end', () => console.log('Event fired: end'))
console.groupEnd()
console.group('Connecting...')
await remote.connect()
console.groupEnd()
console.group('Ending...')
await remote.end()
console.groupEnd()
console.group('Connecting again...')
await remote.connect()
console.groupEnd()
Expected Behavior
Setting up listeners
Connecting...
Event fired: connect
Event fired: connected
Ending...
Event fired: end
Event fired: close
Connecting again...
Event fired: reconnect
Event fired: connect
Event fired: connected
Actual
Setting up listeners
Connecting...
Event fired: connect
Ending...
Connecting again...
Event fired: connect
Furthermore, it's not clear to me when the offline
event should be fired, is it along with the close event? Or is it when there is a external reason for the disconnection? Which then would be brought along side an error event?
Documentation used to base these assumptions:
Connected event
Connect event
Close event
End event
Offline event
Reconnect event
Instance New and Instance Gone events
Instance New and Instance Gone are fired once per instance type, but only for the first connection.
Before the code block below was executed, the instances called docker
, core
, testserviceb
and servicesCatalog
were created, but I think they are not relevant to the behaviour.
const remote = new VrpcRemote({
broker: `wss:${window.location.host}/mqtt`,
domain: 'internal.cybus',
bestEffort: true,
username,
password
})
console.group('Setting up listeners')
remote.on('instanceNew', (added) => console.log('Event fired: instanceNew', added))
remote.on('instanceGone', (gone) => console.log('Event fired: instanceGone', gone))
console.groupEnd()
console.group('Connecting...')
await remote.connect()
console.groupEnd()
console.group('Ending...')
await remote.end()
console.groupEnd()
console.group('Connecting again...')
await remote.connect()
console.groupEnd()
Expected Behavior
Setting up listeners
Connecting...
Event fired: instanceNew ["docker", "core"]
Event fired: instanceNew ["testserviceb"]
Event fired: instanceNew ["servicesCatalog"]
Ending...
Connecting again...
Event fired: instanceNew ["docker", "core"]
Event fired: instanceNew ["testserviceb"]
Event fired: instanceNew ["servicesCatalog"]
Actual
Setting up listeners
Connecting...
Event fired: instanceNew ["docker", "core"]
Event fired: instanceNew ["testserviceb"]
Event fired: instanceNew ["servicesCatalog"]
Ending...
Connecting again...
Documentation:
InstanceGone Event
InstanceNew Event
Error events
Error events seems to only fire on connection issues, due to bad authentication arguments/wrong domain configuration
If I turn off the broker and agents during an active connection, no error event is fired.
Documentation:
Desktop
If you need further context/I missed something, please let me know.
Almost all links in the Examples section of the README are 404.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.