How to schedule a task in Shopware 6 - cron

I have created a custom scheduled task. I have registered it as well using the following tutorial:
https://developer.shopware.com/docs/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task#overview
However, in my database, the status of this task is still "queued" instead of "scheduled". This stops the task from executing. How to fix this? I am currently working on localhost.

Status queued means that a message to execute that task was dispatched to the message queue. If the status does not change automatically that indicates that now worker executed the messages from the queue.
By default (for dev setups!) there is a AdminWorker, which will poll and execute messages from the queue as long as the shopware administration is open in a browser. You can also start a worker manually per CLI:
bin/console messenger:consume
You can find more information how to work with the message queue and how to start workers in the official docs.

I had exactly the same problem.
After I had created and registered my task, it was displayed in the database as "queued" and accordingly not executed.
By manually changing it to "scheduled" it was then executed once and set back to "queued".
Of course unusable for productive use.
My error was the following:
In the services.xml I had passed additional parameters for my handler.
Accordingly my handler had a __construct() method.
However, the class inherits from "ScheduledTaskHandler" which in turn also has a constructor and expects the parameter "scheduledTaskRepository".
This repository is used to update the status.
The solution:
inject the service scheduled_task.repository in the services.xml into your custom handler
call in the construct method of the handler: parent::__construct($scheduledTaskRepository);.
In the end it should like this:
<?php declare(strict_types=1);
class myCustomHandler extends ScheduledTaskHandler
{
public function __construct(
EntityRepository $scheduledTaskRepository,
[...]
) {
parent::__construct($scheduledTaskRepository);
[...]
}
public static function getHandledMessages(): iterable
{
return [ MyCustomTask::class ];
}
public function run(): void
{
file_put_contents('test.txt', 'test');
}
}

Related

Migrating the code from Bot Framework V3 to V4

I have more question while migrating the dialog from V3 to V4. below is our code.
In v3, we were using
Microsoft.Bot.Builder.Dialogs.Conversation.SendAsync(conversationContext.CurrentActivity, new RootDialog());
public class RootDialog : IDialog {
public RootDialog()
{
.....
}
public async Task StartAsync(IDialogContext context)
{
context.Wait(this.MessageReceivedAsync);
}
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
}
In the MessageReceivedAsync, we used the context.Wait(), context.Done() and context.PostAsync().
Can you recommend how to replace in the V4? And what's the alertnative for Microsoft.Bot.Builder.Dialogs.Conversation.SendAsync in V4?
These APIs are all gone. Here are the explanations of their replacements in V4:
context.Wait(…)
This method was used to tell the dialog system what method to invoke next on your class when a new activity arrived and is now gone. Instead you now subclass Dialog and override several methods for various lifecycle events:
BeginDialogAsync - called when the dialog is first pushed on the stack by bot code or another dialog calling BeginDialogAsync on the DialogContext.
ContinueDialogAsync - called when a new activity comes in and the bot calls ContinueDialog on the DialogContext.
ResumeDialogAsync - called when another dialog on the stack has completed and a dialog that was previously on the stack is now at the top of the stack.
RepromptDialogAsync - called when an explicit request has been made to reprompt the user. This is basically a way to tell the dialog that nothing has changed, but that it should pick up from where it left off again by sending whatever activity it last sent.
EndDialogAsync - called when the dialog has indicated its done and is being popped off the stack.
context.Done()/.Fail()
This was one of the way you reported the status of your dialog, but this is now accomplished by returning a DialogTurnResult from most of the aforementioned lifecycle methods. One of the properties is named Status and is of type DialogTurnStatus which has values that indicate the current state of the dialog. For example:
Waiting - the dialog sent some activities and is awaiting more input and should remain at the top of the stack.
Complete - the dialog has completed it's work and should be ended and popped off the stack. When this state is returned, callers can also investigate the output of the dialog (if it has one) which is passed back via the DialogTurnResult::Result property.
Cancelled - the dialog was cancelled part of the way through its work.
context.PostAsync()/Conversation.SendAsync
These were both used to respond back to the user. Both are now replaced by calling SendActivityAsync on the ITurnContext that is accessible via the Context property of the DialogContext instance that is passed into most of the aforementioned lifecycle methods as a parameter. NOTE: a couple of the lifecycle methods actually receive an ITurnContext parameter directly and then you just use that.

Response from service as a callback is not concurrent in actionscript?

I am developing an AIR application for iOS/ Android and I am using a backend service for database operations. The backend service provides asynchronous API's for loading and saving the data. I happen to stumble at a piece of logic which caught my attention:
Main
public funciton loadPlayerData():void
{
service.loadData();
// Busy lock
while( !service.client == true );
// Do some stuff after the client is received
}
Service
public function loadData()
{
// Call the external service and specify success callback as
// onSuccess
}
public function onSuccess():void
{
this.client = true;
}
public var client:Boolean = false;
What I am trying to do in the above code is that I am calling an async operation on service and while it is fetching data from server, I am busy spinning waiting for the client to set true in the callback. According to my understanding, this is how locking is done for resources in operating system and all. ( Though there are more elegant solutions in operating system other than busy wait ).
But the results are such that the Main gets stuck in an infinite busy waiting implying that onSuccess never gets called. The reason, according to my understanding is that until and unless the the current execution ends ( or when the stack of current execution is completely popped out), control is not given to the callback Function and hence my implementation results in never ending spin wheel. My basic assumption that thread is multiplexed from time point of view is flawed and thats the explanation I can deduce from the premise.
I want to know whats the actual reason behind the above scenario? How far I am correct in my deduction and what are the details behind execution of actionscript code in scenario like these ?
The AS3 runtime is not multithreaded - your script runs on a single thread with certain operations internally running on a separate thread (like network calls, etc.) The only way to properly handle your situation is to split up your work into multiple steps; you then initiate the first step (calling the remote service) and pass a callback function. There's no need to wait in a loop (in fact, it hurts you as you discovered) - when the network call is done, your callback will be called and you can initiate the next step of your processing. Until this 2nd step is called, the rest of your program should assume that the data from the remote service is not available.
Your code would be something like:
public funciton loadPlayerData():void
{
service.loadData();
// Nothing else here - you must wait for the data
// to be avaiable.
}
public function loadData()
{
// Call the external service and specify success callback as
// onSuccess
}
public function onSuccess():void
{
// Call logic that performs "Do some stuff
// after the client is received" from your
// question.
}
I think this should solve the issue, depending on how you determine that onSuccess is called (I assume its a function for an Event Listener.)
First off, your Service class needs to inherit EventDispatcher, either directly or indirectly, so that you gain access to dispatchEvent(event) function.
Main
public funciton loadPlayerData():void
{
service.loadData();
service.addEventListener(Event.COMPLETE, onServiceLoadedData);
}
private function onServiceLoadedData(e:Event):void{
...
}
Service
...
public function onSuccess():void
{
//after everything has been loaded
dispatchEvent(new Event(Event.COMPLETE));
}
As a side note, if you need to access stuff from your Service class and you don't want to handle it through setter/getter variables and such like, you can make a custom Event and pass all the necessary Information there.

Using Camel Processor as custom component

I want to make a custom camel processor to behave as a custom component.I read it as it as possible from http://camel.apache.org/processor.html - section--> Turning your processor into a full component.
Here the Custom Processor created will have to do the job when i call
someComponent://action1?param1=value1&param2=value2
in the route.
For this i created a sample component using maven catalog.This created Endpoint,Consumer, Producer and Component classes.
The link says that the component should return ProcessorEndpoint which i have done.
So, Endpoint looks as below
public class SampleEndpoint extends ProcessorEndpoint{
// Automatically Generated code begins
public Producer createProducer() throws Exception{
return new SampleProducer(this, processor);
}
public Consumer createConsumer() throws Exception{
throw new UnsupportedOperationException("This operation is not permitted....");
}
// Automatically generated code ends here
//added below to make custom processor work for custom component
public Processor createProcessor(Processor processor){
return new SampleProcessor();
}
}
But, here the code in the processor is not getting executed instead the code in the SampleProducer gets executed.
Here i want the processor to be excuted.How do i do that?
When extending ProcessorEndpoint, the Producer from createProducer() will handle the exchange, i.e. Producer.process(Exchange exchange).
This is why you are seeing SampleProducer being used. But if you wanted to delegate to a processor, you could probably just change your code to be:
return new SampleProducer(this, new SampleProcessor());
My best advice would be to attach a debugger and put breakpoints in your SampleEndpoint, SampleProducer and SampleProcessor methods to see what gets called and when.

Accessing WinForm UI from Rhino Service Bus consumer [duplicate]

This question already has answers here:
Invoke or BeginInvoke cannot be called on a control until the window handle has been created
(8 answers)
Closed 9 years ago.
I have a WinForm screen that is also a message consumer (using Rhino ESB). If I try to update anything on the screen when I receive a message, nothing happens. A call to Invoke gives me an error that the handle is not created. The form is definitely created though, I'm firing a message on button click on the form and the background process sends a message back. It's with this return message I want to update the UI.
THIS IS NOT A DUPLICATE QUESTION, NONE OF THE SUGGESTED SOLUTIONS WORK.
I believe the difference here may be because I'm using Rhino Service bus. Rhino may be constructing a separate instance of my form rather than the one I'm using. I think what I probably need to do is to have Rhino use my instance of the form as the consumer by passing my instance into the IoC container Rhino is using. Another alternative is to move the Consumer off to it's own class and inject my Form into the consumer, and put a public method on my Form for the Consumer to use. This may work fine with my app because this is the main form and will never be disposed unless the app is closed. This would become problematic on another form that may be instantiated multiple times. Perhaps I could have my form "observe" another static object that a separate Consumer class updates. Please give suggestions as to the best approach.
public partial class MainForm : Form, ConsumerOf<MoveJobCompletedEvent>
{
public void Consume(MoveJobCompletedEvent message)
{
// This does nothing!
txtLogs.Text = "\nJob completed!";
}
}
This throws an error:
this.BeginInvoke((MethodInvoker)delegate
{
txtLogs.Text += "\nJob job completed!";
});
ERROR: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
It seems that you're consuming a JobCompleted event before the window handle is created. You could try the following:
public partial class MainForm : Form, ConsumerOf<MoveJobCompletedEvent>
{
public void Consume(MoveJobCompletedEvent message)
{
if (!this.HandleCreated)
return;
this.BeginInvoke((MethodInvoker)delegate
{
txtLogs.Text += "\nJob job completed!";
});
}
}

Silverlight - Waiting for asynchronous call to finish before returning from a method

I have a Silverlight application that uses WCF services and also uses the Wintellect Power Threading library to ensure logic executes fully before the application continues. This is achieved by calling back to the application using delegates so it can continue after the service call has completely finished.
I wish to achieve the same thing in another part of my application but without the use of callbacks e.g. call method that uses WCF service to say load an object from the database, wait for this to return and then return the Id of the object from the original method called.
The only way I could see to do this was to carry out the call to the WCF service in a helper library which loads the object on a different thread and the original method would keep checking the helper library (using static variables) to wait for it to complete and then return it.
Is this the best way to achieve this functionality? If so here are details of my implementation which is not working correctly.
public class MyHelper
{
private static Thread _thread;
private static User _loadedObject;
public static GetUser()
{
return _loadedObject;
}
public static void LoadObject(int userId)
{
_loadedObject = null;
ParameterizedThreadStart ts = new ParameterizedThreadStart(DoWork);
_thread = new Thread(ts);
_thread.Start(userId);
}
private static void DoWork(object parameter)
{
var ae = new AsyncEnumerator();
ae.BeginExecute(DoWorkWorker(ae, Convert.ToInt32(parameter)), ae.EndExecute);
}
private static IEnumerator<Int32> DoWorkWorker(AsyncEnumerator ae, int userId)
{
// Create a service using a helper method
var service = ServiceHelper.GetService<IUserServiceAsync>();
service.BeginGetUserById(userId, ae.End(), null);
yield return 1;
_loadedObject = service.EndGetUserById(ae.DequeueAsyncResult());
_thread.Abort();
}
}
My method then is:
public int GetUser(int userId)
{
MyHelper.LoadObject(userId);
User user = MyHelper.GetUser();
while (user == null)
{
Thread.Sleep(1000);
user = MyHelper.GetUser();
}
return user.Id;
}
The call to the get the user is executed on a different thread in the helper method but never returns. Perhaps this is due to the yield and the calling method sleeping. I have checked the call to get the user is on a different thread so I think everything should be kept separate,
The whole construct you are using does not match current best practices of Silverlight. In Silverlight your data access methods (via WebServices of course) are executed asynchronously. You should not design around that, but adapt your design accordingly.
However calling services sequentially (which is different than synchonously) can be valid in some scenarios. In this blog post I have shown how to achieve this by subscribing the Completed event of the remote call and block the UI in the meantime, with which the workflow looks and feels like normal async calls.
I believe calls to the server from Silverlight apps use events that fire on the UI thread; I think that's part of the Silverlight host environment in the browser and can't be worked around. So trying to call back to the server from another thread is never going to end well. If you are waiting in program code in the UI thread, your never going to get the call result events from your WCF calls.
You can simulate a synchronous call from a non-UI thread with a callback on the UI thread, but that is probably not what you want. It's better to bite the bullet and make your program logic work with the async calls Silverlight gives you.
If you code against the Interface created for your service reference you can call the Begin and End methods 'synchronously' for each one of your service calls, we then pass in an Action<T> to execute after the End methods has completed. Take note that you have to do this from a dispatcher. This is very close to making a synchronous call as the code to run after the call is still written where the call is made, and it executes after the service call is completed. It does however involve creating wrapper methods but we also worked around that by hiding our wrappers and generating them automatically. Seems like a lot of work but isn't, and ends up being more elegant than all the event handlers etc. Let me know if you need more info on this pattern

Resources