I have created a shiny app on the backbone of {golem} + {brochure}, both fantastic packages by #ColinFay. When using single R sessions as suggested in Chapter 16, it is better to use inner-session asynchronous code, so that users aren't blocked waiting for a render function.
In my case I have four modules that output a plot on a dashboard. I would like to send this plotting logic elsewhere while the user interacts with the app. Since brochure is natively a multi-session app infrastructure, is cross-session async capable of keeping users seperate being that it is two separate sessions, or will there still be issues between users on the same endpoint (session)?
TL;DR
Is each brochure page session restricted to one user? or as the docs say, is each page opened a new session and unique (thus only needing cross-session async) -- scroll down to design pattern here to see brochure structure
Do I need to implement inner-session async code blocks with promises + future?
I know this isnt the best SO question but I really could use some lexical insight!
Related
As described in RStudio reference docs,
shiny server functions can optionally include session as a parameter (e.g. function(input, output, session)). The session object is an environment that can be used to access information and functionality relating to the session.
I never use this parameter in my apps and could be missing something.
What are the practical uses of the session parameter?
Here is my attempt for an overview:
List of use cases:
Customised user interfaces
chat room
games
Javascript communication
Trigger a function when session is ended
global reactive values for modularised shiny apps
updating inputs
Trigger a function when session is ended
E.g. close a database connection, see
How to implement a cleanup routine in R Shiny?.
Stopping a shiny app when browser / session is closed:
How to stop running shiny app by closing the browser window?
Customising the user interface
The user interface will be dependent on the device from which its called.
Is it a mobile or pc, which screen resolution is used etc.
Using fluid pages in the ui will help, but certainly has there limits as well.
With session$clientData$output_{OUTPUT_ID}_height and session$clientData$output_{OUTPUT_ID}_width
you can track how your outputs are rendered for your user.
You could make live adjustments (dont insert my huge title if the plot is too small). Or you can track
the data and adjust your ui after finding the most common ui settings of your users.
User interactions
You can create a local/secret reactiveValue() within that session / for that user and you can set
reactiveValues() outside the server function for "global infos" that are accessible across users/sessions.
That way you can share infos across sessions, but also hide specific values for certain users.
Use Case example: Chat room
https://shiny.rstudio.com/gallery/chat-room.html
Use Case example: Games
Can R Shiny display different views for two simultaneous users, interacting with one another?
Share data between modules
As mentioned in the comment, there is a current open bounty where it is asked to have
global reactive values for modularised shiny apps.
See Shiny modules: Destroy module ui if server-function fails
and
https://appsilon.com/super-solutions-for-shiny-architecture-1-of-5-using-session-data/?nabe=4634331497365504:0.
Finally, there is Some functionality you indirectly use, since there are good wrapper functions / packages for that.
Sending messages to Javascript
(There are good wrappers for this. E.g. shinyjs package).
If you want to integrate javascript in your app and send a message from shiny to javascript you can do it with
session:sendCustomMessage().
See, e.g.
http://www.blog.rdata.lu/post/2017-09-16-communication-between-r-and-d3js/ and
https://shiny.rstudio.com/articles/js-send-message.html.
Updating inputs
You could use session$sendInputMessage(inputId, message) to update inputs.
But again there are already more convenient wrapper functions for this, e.g. updateTextInput().
But it´s interesting to keep in mind for inputs that dont have a helper function.
General overview:
https://shiny.rstudio.com/reference/shiny/latest/session.html
Suppose you have template1 and template2, both subscribing using this.subscribe('samePublication', sameArg) inside their .onCreated() and this.autorun().
What happens when we have something like this:
<template name="template3">
{{>template1}}
{{>template2}}
</template>
Will this.subscribe('samePublication', sameArg) run once for each template, and hit my server and DB twice?
Should I put this.subscribe() inside the .onCreated() on template3?
My own understanding is 'no' and 'no', after having read this: http://docs.meteor.com/#/full/meteor_subscribe
Hoping someone more knowledgeable can comment.
Thanks in advance.
In my experience, the subscriptions load and hit your DB every time you route to the view and render the template.
While the general best practice (probably to promote modularity) is to use template level subscriptions, I have found that if a route is heavily used and frequently changed to and it involves large amounts of docs, then it makes more performance sense to load those subscriptions on client startup and share between views.
Did you know you can pass an argument with a subscription to a publication and use the argument in your publication to filter the results? Using this often makes a big difference on the performance without falling back to global subscriptions.
PS: I am working on parallel subscriptions that do not start until after the loading of 'fast' landing pages, so that when the user switches to a heavily subscribed page, the parallel loading would already have completed, but would not affect the 'first impressions' of the user.
I am trying to make a chat application in meteorJS and i was thinking of making a seperate collection for each groups dynamically when they initiate chat, I want to publish and subscribe that collection for transmitting chat information and all the group user can subscribe it, but i am not being able to create a collection dynamically.
I tried making a function which gets call when the user subscribe the collection.
this.createDb =(name) ->
#ChatDb = new Mongo.Collection(name)
return true
everything is fine, but when i subscribe this collection from client side, ChatDb is unknown, Can any one help me with this, that would be great. :)
ps- i am writing code in angular-meteor framework
Andrew Mao's answer to a similiar question:
In most instances, you probably don't want to create multiple
collections, but instead use one collection and send views of it to
clients depending on their subscription.
You may want to check out the
https://github.com/mizzao/meteor-partitioner package I've built which
is designed especially for this purpose, and includes an example for
how to do this for multiple chat rooms. You can also see
https://github.com/mizzao/CrowdMapper for an implemented example.
I haven't done Meteor for a while now so I couldn't give you a solid answer. But I remember quite clearly that creating collections dynamically is not the recommended way for achieving what you want to do.
In my multi-user meteor application design I want to enable users to be able to create and store their own reactive dashboards to visualize data that they own within the applications database. For example, a user may have an object in the database representing the real-time disk usage of a processor. I want them to be able to submit/store html say to represent a dynamic dial as their dashboard. Another user may have their own weather station and want a dashboard with a last 24 hours thermometer and pressure trend. When they call up one of their stored dashboards it is rendered and would update as their data changes.
Can anyone point to example code or explain how to accomplish this? Or, authoritatively explain why it cannot be done in the framework. I have come across various dynamic API's but nothing that fits the bill. I.e. UI.renderWithData and Meteor._def_template.
The following topic was very similar to my questions and it got me a good start and I figured it out and posted and answer there.
How to make meteor evaluate user defined template text
I am writing an Adobe AIR application using PureMVC.
Imagine that I have an page-based application view ( using ViewStack ), and user is navigating through this pages in some way ( like clicking the button or whatever ).
Now for example I have an Account Infromation page which when instantiated or showed again needs to load the data from WebService ( for example email, account balance and username ), and when the data is returned I want to show it on my Account Information page in the proper labels.
The problem is when I will execute this three Web Calls, each of them will return different resultEvent at different time. I am wondering what is the best way to get the information that ALL of the service calls returned results, so I know that I can finally show all the results at once ( and maybe before this happens play some loading screen ).
I really don't know much about PureMVC, but the as3commons-async library is great for managing async calls and should work just fine in any framework-setup
http://as3commons.org/as3-commons-async/
In your case, you could create 3 classes implementing IOperation or IAsyncCommand (depending on if you plan to execute the operations immediately or deferred) encapsulating your RPCs.
After that is done you simply create a new CompositeCommand and add the operations to its queue.
When all is done, CompositeCommand will fire an OperationEvent.COMPLETE
BTW, the library even includes some pre-implemented common Flex Operations, such as HTTPRequest, when you download the as3commons-asyc-flex package as well.
I would do it in this way:
Create a proxy for each of three information entities (EMailProxy, BalanceProxy, UsernameProxy);
Create a delegate class which handles the interaction with your WebService (something like "public class WSConnector implements IResponder{...}"), which is used by the proxies to call the end ws-methods;
Create a proxy which coordinates all the three results (CoordProxy);
Choose a mediator which will coordinate all the three calls (for example it could be done by your ApplicationMediator);
Create notification constants for all proxy results (GET_EMAIL_RESULT, GET_BALANCE_RESULT, GET_USERNAME_RESULT, COORD_RESULT);
Let the ApplicationMediator get all 4 notifications;
it is important that you should not only wait for all three results but also be ready for some errors and their interpretation. That is why a simple counter could be too weak.
The overall workflow could look like this:
The user initiates the process;
Some mediator gets an event from your GUI-component and sends a notification like DO_TRIPLECALL;
The ApplicationMediator catches this notification, drops the state of the CoordProxy and calls all 3 methods from your proxies (getEMail, getBalance, getUsername).
The responses are coming asynchronously. Each proxy gets its response from the delegate, changes its own data object and sends an appropriate notification.
The ApplicationMediator catches those notifications and changes the state of the CoordProxy. When all three responses are there (may be not all are successful) the CoordProxy sends a notification with the overall result.
I know it is not the best approach to do such an interaction through mediators. The initial idea was to use commands for all "business logic" decisions. But it can be too boring to create the bureaucracy.
I hope it can help you. I would be glad to know your solution and discuss it here.