I'm wanting to create a background worker for a ZF application I'm working on but I'm baffled not as much about the software architecture but more of the filesystem architecture.
The worker would be triggered by a controller to perform some tasks and then the controller would check up on the status of the worker so this bit has been covered.
From the folder structure point of view where should these the code for the worker sit in?
application/
models/
services/
worker/
application/ --> code for the worker (standard ZF structure)
worker.php --> entry-point to the worker
Or
application/
controllers/
WorkerController.php
models/
Worker/
Class.php
Class2.php
services/
worker.php --> entry-point to the worker
Bear in mind the configuration of the main application and the worker are almost identical (especially same db connection credentials, autoloading settings) and the worker would need to access the main application's models.
Any advice or opinions would be appreciated.
Many thanks,
Angel
If the worker is triggered via cronjob, then you could make the worker component a module, so it has its own controllers, views, etc. Then - as #MonkeyMonkey notes - your commandline script could make MVC requests to that module.
But it seems to me that this worker component might function more naturally as a service, a class containing functionality that gets invoked by your cron-triggered cli script. ZF-based cli scripts - optionally using Zend_Console_Getopt, which is pretty cool - can use the same config and Bootstrap class, selectively bootstrap resources (some might not be required for the cli-based task), and use the same autoloaders as the standard MVC app.
As you note, these workers will update a status table that would be accessible to the web-facing portion of the app, so those pages can read/render the status on request.
As for the filesystem structure of that, you could name these service classes something like Application_Service_MyWorker stored in the file application/services/MyWorker.php. Perhaps even push down further using something like Application_Service_Worker_MyWorker stored in application/services/Worker/MyWorker.php, though this latter might require adding another resource-type entry into the resource autoloader, similar to the way that mappers and DbTable-based models are defined in Zend_Application_Module_Autoloader.
MVC is not only helpful in web environments (Apache), you can use it for "background workers" as well (the view is your console), you just need to add a cli.php or something, handle cli arguments (module, controller, action), create the request object and pass it to the dispatcher.
So how ever your triggering of the background worker works (exec?), call your newly create cli.php and enjoy the features of your zf application (configuration, autoloading, ..).
For short, I can't tell you how exactly a cli.php would look like, but I found this tutorial:
Using Zend Framework from the Command Line
Important object for you: Zend_Controller_Request_Simple
Related
I have a rest endpoint which would start the scheduler of loading a XML to memory. Whenever I hit that rest endpoint, it loads the XML in memory and would return the XML after its ready (would take 10 - 15 seconds). When the same endpoint is accessed again, it would return the cached XML. Everything works fine but for now I have to manually hit the endpoint for the scheduler to start. Is there a way to hit the endpoint automatically via a simple code in startup? Or is there any other solution for this?
Normally, a component in the Nucleus is instantiated at first access, not at system start-up.
The way to have anything done at start-up in ATG is to create your component, and then to add its nucleus path to the list of initial services in the /Initial component (or from one of the many other Initial components changed off of it)
The component should be globally scoped. Because /Initial is instantiated at start-up, the services it references will also be instantiated as dependencies.
If your component is a POJO, then the no argument constructor will be invoked on component start-up, then the setX method will be called for each property with a value defined in its properties file.
If your component is extended from Generic Service, then additionally, beforeSet and afterSet methods will be called, before and after the set methods are invoked, if they exist, and finally doStartUp will be called.
This is all part of the fundamental lifecycle of components that the Nucleus manages.
This gives you a number of hooks with which to invoke your custom code.
Now, in your question, you ask how to call a REST endpoint at start-up. However, I believe what you actually want to ask is how to ensure that a particular piece of code gets executed at system start-up. A REST endpoint is how you are triggering it today, manually, from outside the Nucleus. But that does not mean that it must call a REST end point if it is to be automatically called at start up.
The easiest way to achieve what you want is
define a class that extends GenericService
override the doStartUp method
put the code you want to execute in this method, or invoke the code on another component from here
define a globally scoped component for the class
Add the component to the initialServices property of the Initial component
Restart the server and check that your code is being called at start-up. Put some debug statements in, and switch debug logging on in your layer.
Note, you may actually also want to think about whether you really need to invoke your code at system start-up. Anything in initial services adds to the start time of the server. Depending on your requirements, it may be better to do it on first access of your application service rather than at server start-up.
I have an RCP 3.7 application that requires two database connections, the code for each database is in a separate bundle. Previously the database startup was done in the Activator.start() methods. I have heavily refactored the code to move the database startup into two Declarative Services. This achieved the goal of breaking the tight coupling and excessive package exposure across bundles (almost everything was exported).
The challenge I have now is that the two Services do not start quickly enough, the workbench loads and I'm getting thread violations. I have both services set immediate=true. The bundle start order is eclipse.osgi at -1 (default), equinox.ds and equinox.common at 2, core.runtime at default. I have tried adding start levels for my bundles but it did not help so removed them.
Any thoughts or suggestions on how to ensure the database starts before the service returns?
It looks like you are accessing SWT from within the DS activation thread. Please use Display.asyncExec to access SWT code from other threads. See PlatformUI.getWorkbench for accessing the Display.
I need to build a few tasks that import various data from outside APIs in my SailsJS project. I was thinking of using laterJS (unless there's a better option).
Is there a best practice for the location and loading of these "task" files?
The place where I think it should go is file config/bootstrap.js.
Description of this file from sails-docs:
This is an asynchronous boostrap function that runs before your Sails app gets lifted (i.e. > starts up). This gives you an opportunity to set up your data model, run jobs, or perform
some special logic.
So I currently have an application independent of Play which may take a long time in its execution.
I want to put a UI on top of it using Play where the application may be invoked and to display some of the details of the execution inside of the application to the user. I would like the page to be updated automatically as the execution proceeds e.g. if a variable in the application increments this would be reflected on the page.
I'm not sure where to begin with this - do I need to split the application up into models + controllers ? Or do I just need to have code in a controller to instantiate the classes I have already coded and call the methods I need ?
What about constantly showing the execution state on the page?
Any resources I should know about/read ? Code examples?
Thanks
You may have already done so, but a good starting point is to create a skeleton Play application using the play new command, while referring the creating a new application section. You will have "views" (HTML template pages) and one controller (in Application.scala). You could add more controllers, but as you will have just a single page that should suffice.
You can add jars from your app (if it's a JVM app) to the lib directory of your Play application. From this: "Or do I just need to have code in a controller to instantiate the classes I have already coded and call the methods I need?" it sounds like you would be happy to have your app run in the process of the Jetty + Play server. Check out the Global object for starting your app at process startup.
Check out the section on comet sockets for sending updates from the Play app to the browser. You'll need a bit of Javascript in the web page.
Do you want to have this application running outside of play, perhaps on another server? Can you modify the application, or is this 3rd party software?
If so, you have to have some way to send data back and forth between your play front end and your application. You can either have your application expose a websocket, and then your play front end and your application can push data back and forth to each other. You can then have your client page have a websocket open to you play front end, and then play can push the updates to the client. If your application can't support a websocket, you could also expose some URLs on your front end for the application to POST to. You can then use some sort of message bus or database mechanism (RabbitMQ, redis, Mongo capped collection, or even just a shared Queue object) so that the front end websocket can get those updates and send them to the client.
Workers JSNI at GWT svn
It looks like WebWorkers have not been fully implemented yet. I know that elemental is in early stage of development but might be someone already have tried to make it works?
The problem with web workers is that they don't really fit the standard GWT/Java model - in my opinion they barely fit the standard JS model.
Web workers work by passing data back and forth between what are essentially different JavaScript VMs. That data must be in the form of a string, and each worker has to load its JS separately. This means that no variables declared in one worker (or the main page) is accessible from another, unless it is passed as part of the string data, pushed back and forth between workers.
So how does this work when you consider GWT/Java? From the Java perspective, this is not equivalent to multiple threads, but multiple JVMs! The different processes can only communicate by passing Strings (or more importantly, not Java objects) back and forth, and cannot share any other state. Even static variables might be different between the two virtual machines.
From the link you posted, check out the source of JsWorker - you can create an instance of this via JsWindow.newWorker with the url of the JS script to start with, and JsWorker supports methods to listen for responses, and to send it messages to give it work to do.
That script could be a GWT compiled object - but it would be a separate module and entrypoint than the original app, so that it only has the code it can reasonably run, and doesn't try to start drawing on the page when it loads. It would probably need to use a linker that would only load the JS, and wouldn't assume an iframe on the 'page'.
The GWT-NS project has some web worker samples already, built using their own linker to construct js files to load to load in the worker, and some other convenience pieces as well.