I would like to know the best practice to initialize an Electron app.
I decided to manage the configuration on the main side.
I have a class that load the config.json file with all the methods to get properties.
I have doubts about the flow to populate the renderer view with data.
Here my thoughts:
renderer (function) -> preload (invoke) -> main (handle) -> return to preload -> return to renderer
main (webContents.send) -> preload.on(callback) -> renderer (callback)
Is there any other better way to do that?
Is it correct to have all the config on the main side?
thank you
Using the main process to initialise your application is the correct way to go.
Prior to creating your main window, you can initialise your configuration module and get the applications configuration data.
Next, create your main window with new BrowserWindow() but set the show option to false. EG: show: false. This will hide the window.
Next, use IPC to communicate from your main process to your render process any configuration data necessary to correctly set-up the content of your render. IE: Send from the main process: send(channel, ...args) and receive in the render process: ipcRenderer.on(channel, listener).
Finally, show() your window.
This is the flow I have used in the past and it works well.
Additionally, if you have a 'configuration' window where you can make application setting changes:
[Render Process] - Communicate the individual change via IPC to the main process.
[Main Process] - Have your main process configuration module update the specific in-memory configuration object value.
[Main Process] - JSON.stringify() the configuration object and (re)write it over the current (config.json) file.
[Main Process] - Communicate the updated configuration object via IPC to the render process.
[Render Process] - Listen for and when received, update any content via the use of a render side configuration module.
I prefer the above process because:
The render process should only be used to render content. Anything other may slow down or freeze the render process.
The main process can handle the heavy lifting such as updating the (configuration) object, (re)writing files, etc.
Simple logic is kept in the render, such as the detection and transmission of UI events back to the main process and repainting content when requested to do so by the main process.
Finally, should your UI update after a settings change, you know the whole process is working correctly.
I use the above technique for not only setting (configuration) changes but to remember user customisation of the UI such as columns widths and ordering, showing or hiding panels, selection and ordering of favourite items, etc.
Related
We are using apache beam and would like to setup the logback MDC. logback MDC is a great GREAT resource when you have a request come in and you store let's say a userId (in our case, it's custId, fileId, requestId), then anytime a developer logs, it magically stamps that information on to the developers log. the developer no longer forgets to add it every log statement he adds.
I am starting in an end to end integration type test with apache beam direct runner embedded in our microservice for testing (in production, the microservice calls dataflow). currently, I am see that the MDC is good up until after the expand() methods are called. Once the processElement methods are called, the context is of course gone since I am in another thread.
So, trying to fix this piece first. Where should I put this context such that I can restore it at the beginning of this thread.
As an example, if I have an Executor.execute(runnable), then I simply transfer context using that runnable like so
public class MDCContextRunnable implements Runnable {
private final Map<String, String> mdcSnapshot;
private Runnable runnable;
public MDCContextRunnable(Runnable runnable) {
this.runnable = runnable;
mdcSnapshot = MDC.getCopyOfContextMap();
}
#Override
public void run() {
try {
MDC.setContextMap(mdcSnapshot);
runnable.run();
} Catch {
//Must log errors before mdc is cleared
log.error("message", e);. /// Logs error and MDC
} finally {
MDC.clear();
}
}
}
so I need to do the same with apache beam basically. I need to
Have a point to capture the MDC
Have a point to restore the MDC
Have a point to clear out the MDC to prevent it leaking to another request(really in case I missed something which seems to happen now and then)
Any ideas on how to do this?
oh, bonus points if it the MDC can be there when any exceptions are logged by the framework!!!! (ie. ideally, frameworks are supposed to do this for you but apache beam seems like it is not doing this. Most web frameworks have this built in).
thanks,
Dean
Based on the context and examples you gave, it sounds like you want to use MDC to automatically capture more information for your own DoFns. Your best bet for this is, depending on the lifetime you need your context available for, to use either the StartBundle/FinishBundle or Setup/Teardown methods on your DoFns to create your MDC context (see this answer for an explanation of the differences between the two). The important thing is that these methods are executed for each instance of a DoFn, meaning they will be called on the new threads created to execute these DoFns.
Under the Hood
I should explain what's happening here and how this approach differs from your original goal. The way Apache Beam executes is that your written pipeline executes on your own machine and performs pipeline construction (which is where all the expand calls are occurring). However, once a pipeline is constructed, it is sent to a runner which is often executing on a separate application unless it's the Direct Runner, and then the runner either directly executes your user code or runs it in a docker environment.
In your original approach it makes sense that you would successfully apply MDC to all logs until execution begins, because execution might not only be occurring in a different thread, but potentially also a different application or machine. However, the methods described above are executed as part of your user code, so setting up your MDC there will allow it to function on whatever thread/application/machine is executing transforms.
Just keep in mind that those methods get called for every DoFn and you will often have mutiple DoFns per thread, which is something you may need to be wary of depending on how MDC works.
Prior to the most recent SDK I was relying on the ability to access my sideInput inside of startBundle of my DoFn. I’m not sure of the history of refactoring but I seem to be having issues doing this now.
Essentially I have an array that I want to process across within my process() method and the array is reasonably sized that will fit in memory.
Is it valid to expect to access a sideInput within startBundle? And if so, how can I do that if startBundle is sent a Context instead of a ProcessContext?
Example:
#Override
public void startBundle(DoFn<KV<String, Iterable<String>>, String>.Context c) throws Exception {
uniqueIds = Lists.newArrayList(c.sideInput(iterableView));
super.startBundle(c);
}
The history is explained here: Why did #sideInput() method move from Context to ProcessContext in Dataflow beta
Do you need to do any processing on your side input to prepare it for use in processElement? If not, then I'd suggest just using View.asList() or View.asMap() and calling that directly in processElement() -- Dataflow will do caching when possible to make this cheap. (Note View.asList() is currently available on Github and will be in the next Maven release.)
If you need to do processing on your side input, and you are using the (default) GlobalWindow, then you can lazily initialize a local variable from within processElement(). However, if you are using Window.into(), you'll need to invalidate that cache every time the element's window changes.
I have a structure in the mainWindow() of my application as follows:
Within the children directory of the UIAWindow near the top of the image, I am trying to access Item 1, where it is a UIAButton.
This structure is generated from
#import "tuneup/tuneup.js"
goAbout = function(target, app)
{
UIATarget.localTarget().frontMostApp().mainWindow().logElementTree();
};
test("go about", goAbout);
If I add .button() or [1] it raises an exception, so I cannot do something like so
...
UIATarget.localTarget().frontMostApp().mainWindow().buttons().logElementTree();
What can I do to access the object within the children subdirectory of the UIAWindow?
You can access that button by adding .buttons()[0]. The
UIATarget.localTarget().frontMostApp().mainWindow().buttons();
expression returns a javascript array (which has a 0 based indexing).
Here you can find a rather usable documentation:
https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/UIAutomationRef.pdf
Anyway studying this plist is not the most convenient method to explore your object hierarchy. I prefer to check instruments output directy. (Or standard output, if you run instruments from command line.)
That tree hierarchy ended up not meaning anything useful to me, and I ended up utilizing target methods to access the elements of my window. Cheers!
If in spring portlet controller, I have one methof annotated with #ActionMapping and another method annotated with #RenderMapping(params = "action=detail"), I see that to come from method #1 to method #2, we do not call the method#2 directly, instead we set a Actionresponse.setRenderParameter("action", "detail") in method #1 and method#2 will pick it up from here.
My first question is what advantages are we getting from separating the render phase from the Action Phase (or should I say Request Phase)? And also why we do not do a direct method call and instead call the method by setting a render parameter?
To answer your questions
Portlets can co-exist on a page. Irrespective of what action you performed on a portlet, the Portal container will invoke render() method on all the portlets to collect the html fragments and aggregate them, in an effort to prepare the whole page view and serve to the browser. Having 2 methods is not only an advantage but an enforcement to implement the aforementioned requirement which separates the business logic - processAction() that may change the state of your system as #Mark Chorley said, which you are aware of the execution "AND" render logic - render() which decides the view to render, which sometimes you are not aware of the execution.
This is simple, why do you call start() rather then run() on a Thread though you can invoke run method directly. There are many reasons why you shouldn't call the method directly
You are not responsible for the aggregation of html fragments from all the Portlets residing on the page.
You are not the one who make the Public Render parameters available in the render() method of the interested Portlets.
Definitely you dont want to take the headache of delegating the Events to the subscribed portlets
This is what portlets do basically. As to what advantage you get - well it allows you to separate your action (typically modifying data) from preparing data for your view.
Both Action and Render are different stages of a single request. Action requests precede Render requests as you say. "Request phase" sounds a confusing term to me. Action Phase and Render Phase are more helpful terms.
Why you don't call it directly - well the portlet container will do it for you. Also you must remember that the render methods will be called on all the visible portlets, but the action request will target only your portlet.
So given that the portlet container is guaranteed to call all the render methods on all the visible portlets, it doesn't make sense to call the render method manually on one portlet just because the action request targeted it.
If you only have one portlet visible this is perhaps less clear. It makes more sense when you have multiple portlets on a single page.
In Nitrogen, the Erlang web framework, you wire actions like this:
wf:wire(send_message, #event { type=click, postback=send_message })
but if after that you run
wf:wire(send_message, #event { type=click, postback=send_message2 }),
then you get the action wired twice.
How do you unwire the previous action or all actions of an element?
Since events in nitrogen are bound using jquery's bind method. You can use unbind to unbind them. There isn't currently a nitrogen api to unbind an event but you could output the javascript code to unbind it yourself if you so wished.
see action_event.erl for an example of how the binding javascript is output. You can create a similar action/event that removes the binding.
I too was looking for an "unwire" and didn't find it. My work-around was to wf:replace() the element to which the event was wired, and wire the replacement element; I hope that javascript will eventually notice the former bind can never be called and then garbage collect it. I don't know how expensive such abandoned bindings are. My context was a lazy loading of the page, such that a button would initially show a stub, but when clicked would download arbitrarily large content, and henceforth toggle hide/show.
Beyond being nervous about the sophistication of the javascript garbage collection, I'm worried that this may be a bad pattern, and would love to hear others' experience. The only alternative that occurs to me would be to keep state (e.g. data) in the original element and pass that state back with the event message so that the same event handler would act on the "unloaded->loaded_show->loaded_hide->loaded_show" transitions. But I'd prefer not to be calling back to the server for a simple hide/show transition.