How to move Laravel Events into subdirectories and still have them work when broadcasting? - laravel-8

I've moved my Laravel Events into subdirectories, and now my broadcasted messages are not being received. Pusher shows them ok, and if I move them out of the subdirectories then they work as expected, so I believe this is a namespacing issue, but I cannot figure out how to make it work.
The Event I'm focusing on is called TeamInvitationEvent and is located in the Events->Company->Memberships directory.
Here is my Listener:
public function getListeners()
{
$user_id = Auth::id();
return [
'refresh-navigation-top-menu' => '$refresh',
"echo-private:user.{$user_id},TeamInvitationEvent" => 'notifyInvitation',
"echo-private:user.{$user_id},TeamInvitationCancelledEvent" => 'notifyInvitationCancelled',
"echo-private:user.{$user_id},TeamInvitationAcceptedEvent" => 'notifyInvitationAccepted',
"echo-private:user.{$user_id},TeamMemberRemovedEvent" => 'notifyMemberRemoved',
];
}
Here is a screenshot of my Pusher debug console, showing that the user is subscribed to the correct private channel, and that the API Message is being broadcast on that channel:
Here is a list of different ways I've tried to correct for the new namespace:
App.Events.Company.Memberships.TeamInvitationEvent
App\Events\Company\Memberships\TeamInvitationEvent
/App/Events/Company/Memberships/TeamInvitationEvent
.TeamInvitationEvent
There are no errors in the Laravel logs, or in the Pusher logs, and as I mentioned it works as expected if I don't move them into the subdirectory.
I'm running the following in my app:
Laravel v8
Livewire v2
Laravel Echo v1
Pusher

This was embarrassingly obvious, but here's what fixed it:
"echo-private:user.{$user_id},Company\Memberships\TeamInvitationEvent" => 'notifyInvitation'
The docs are very clear that "App\Events" is prepended to all events, so naturally I just needed to add the rest of the namespace to get it working. I looked back and I had actually tried this earlier, but I must have forgot to clear the cache. Big shout-out to #joshhanley on the Livewire Discord chat for getting me sorted on this.
Side Note: using broadcastAs() made this much cleaner:
public function broadcastAs()
{
return 'team.invitation';
}
But don't forget to add a '.' before this custom name in your view, like this:
"echo-private:user.{$user_id},.team.invitation" => 'notifyInvitation'

Related

Raku Cro service subscribing to data "in the background" general guidance

I am attempting to put together a Cro service that has a react/whenever block consuming data "in the background" So unlike many examples of websocket usage with Cro, this has nothing to do with routes that may be accessed via the browser.
My use case is to consume message received via an MQTT topic and do some processing with them. At a later stage in development I might create a supply out of this data, but for now, when data is received it will be stored in a variable and dependant on certain conditions, be sent to another service via a http post.
My thought was to include a provider() in the Cro::HTTP::Server setup like so:
use Cro::HTTP::Log::File;
use Cro::HTTP::Server;
use Routes;
use DataProvider; # Here
my Cro::Service $http = Cro::HTTP::Server.new(
http => <1.1>,
host => ...,
port => ...,
application => [routes(), provider()], # Made this into an array of subs?
after => [
Cro::HTTP::Log::File.new(logs => $*OUT, errors => $*ERR)
]
);
And in the DataProvider.pm6:
use MQTT::Client;
sub provider() is export {
my $mqtt = MQTT::Client.new: server => 'localhost';
react {
whenever $mqtt.subscribe('some/mqtt/topic') {
say "+ topic: { .<topic> } => { .<message>.decode("utf8-c8") }";
}
}
}
This throws a bunch of errors:
A react block:
in sub provider at DataProvider.pm6 (DataProvider) line 5
in block <unit> at service.p6 line 26
Died because of the exception:
Invocant of method 'write' must be an object instance of type
'IO::Socket::Async', not a type object of type 'IO::Socket::Async'. Did
you forget a '.new'?
in method subscribe at /home/cam/raku/share/perl6/site/sources/42C762836A951A1C11586214B78AD34262EC465F (MQTT::Client) line 133
in sub provider at DataProvider.pm6 (DataProvider) line 6
in block <unit> at service.p6 line 26
To be perfectly honest, I am totally guessing that this is how I would approach the need to subscribe to data in the background of a Cro service, but I was not able to find any information on what might be considered the recommended approach.
Initially I had my react/whenever block in the main service.pm6 file, but that did not seem right. And needed to be wrapped in a start{} block because as I have just learned, react is blocking :) and cro was not able to actually start.
But following the pattern of how Routes are implemented seemed logical, but I am missing something. The error speaks about setting up a new method, but I'm not convinced that is the root cause. Routes.pm6 does not have a constructor.
Can anyone point me in the right direction please?
Thanks to all who have provided information, this has been a very valuable learning exercise.
The approach of passing additional sub routines, along side router() in the application parameter to Cro::HTTP::Server.new gave further trouble. (an array is not allowed, and broke routing)
Instead, I have moved the background work into a class of it's own, and given it a start and stop method more akin to Cro::HTTP::Server.
My new approach:
service.pm6
use Cro::HTTP::Log::File;
use Cro::HTTP::Server;
use Routes;
use KlineDataSubscriber; # Moved mqtt functionality here
use Database;
my $dsn = "host=localhost port=5432 dbname=act user=.. password=..";
my $dbh = Database.new :$dsn;
my $mqtt-host = 'localhost';
my $subscriber = KlineDataSubscriber.new :$mqtt-host;
$subscriber.start; # Inspired by $http.start below
my Cro::Service $http = Cro::HTTP::Server.new(
http => <1.1>,
host => ...,
port => ...,
application => routes($dbh), # Basically back the way it was originally
after => [
Cro::HTTP::Log::File.new(logs => $*OUT, errors => $*ERR)
]
);
$http.start;
say "Listening at...";
react {
whenever signal(SIGINT) {
say "Shutting down...";
$subscriber.stop;
$http.stop;
done;
}
}
And in KlineDataSubscriber.pm6
use MQTT::Client;
class KlineDataSubscriber {
has Str $.mqtt-host is required;
has MQTT::Client $.mqtt = Nil;
submethod TWEAK() {
$!mqtt = MQTT::Client.new: server => $!mqtt-host;
await $!mqtt.connect;
}
method start(Str $topic = 'act/feed/exchange/binance/kline-closed/+/json') {
start {
react {
whenever $!mqtt.subscribe($topic) {
say "+ topic: { .<topic> } => { .<message>.decode("utf8-c8") }";
}
}
}
}
method stop() {
# TODO Figure how to unsubscribe and cleanup nicely
}
}
This feels much more "Cro idiomatic" to me, but I would be happy to be corrected.
More importantly, it works as expected and I feel is somewhat future proof. I should be able to create a supply to make real-time data available to the router, and push data to any connected web clients.
I also intend to have a http GET endpoint /status with various checks to ensure everything healthy
The root cause
The error speaks about setting up a new method, but I'm not convinced that is the root cause.
It's not about setting up a new method. It's about a value that should be defined instead being undefined. That typically means a failure to attempt to initialize it, which typically means a failure to call .new.
Can anyone point me in the right direction please?
Hopefully this question helps.
Finding information on a recommended approach
I am totally guessing that this is how I would approach the need to subscribe to data in the background of a Cro service, but I was not able to find any information on what might be considered the recommended approach.
It might be helpful for you to list which of the get-up-to-speed steps you've followed from Getting started with Cro, including the basics but also the "Learn about" steps at the end.
The error message
A react block:
in sub provider ...
Died because of the exception:
...
in method subscribe ...
The error message begins with the built in react construct reporting that it caught an exception (and handled it by throwing its own exception in response). A "backtrace" corresponding to where the react appeared in your code is provided indented from the initial "A react block:".
The error message continues with the react construct summarizing its own exception (Died because ...) and explains itself by reporting the original exception, further indented, in subsequent lines. This includes another backtrace, this time one corresponding to the original exception, which will likely have occurred on a different thread with a different callstack.
(All of Raku's structured multithreading constructs[1] use this two part error reporting approach for exceptions they catch and handle by throwing another exception.)
The first backtrace indicates the react line:
in sub provider at DataProvider.pm6 (DataProvider) line 5
use MQTT::Client;
sub provider() is export {
my $mqtt = MQTT::Client.new: server => 'localhost';
react {
The second backtrace is about the original exception:
Invocant of method 'write' must be an object instance of type
'IO::Socket::Async', not a type object of type 'IO::Socket::Async'. ...
in method subscribe at ... (MQTT::Client) line 133
This reports that the write method called on line 133 of MQTT::Client requires its invocant is an instance of type 'IO::Socket::Async'. The value it got was of that type but was not an instance, but instead a "type object". (All values of non-native types are either type objects or instances of their type.).
The error message concludes with:
Did you forget a '.new'?
This is a succinct hint based on the reality that 99 times out of a hundred the reason a type object is encountered when an instance is required is that code has failed to initialize a variable. (One of the things type objects are used for is to serve the role of "undefined" in languages like Perl.)
So, can you see why something that should have been an initialized instance of 'IO::Socket::Async' is instead an uninitialized one?
Footnotes
[1] Raku's constructs for parallelism, concurrency, and asynchrony follow the structured programming paradigm. See Parallelism, Concurrency, and Asynchrony in Raku for Jonathan Worthington's video presentation of this overall approach. Structured constructs like react can cleanly observe, contain, and manage events that occur anywhere within their execution scope, including errors such as error exceptions, even if they happen on other threads.
You seem to be fine now but when I first saw this I made this https://github.com/jonathanstowe/Cro-MQTT which turns the MQTT client into a first class Cro service.
I haven't released it yet but it may be instructive.

Symfony website got broken once pushed in production

I'm developing a website using Symfony 3.2, and it worked perfectly well on my machine. It also worked perfectly well when I pushed it on our pre-production server. But then when I pushed it on our production server, it got broken.
The first problem I meet is this error, when trying to load a simple page using the News entity:
Error 500: Class 'Fidelise\SignUpBundle\Entity\News' does not exist
And yet that class definitely does exist.
The other problem is, when trying to log in to the website, I get this error:
500 - The request timed out.
Everything else works fine. Why would it start bugging when in production environment? I can also add some code if needed.
EDIT: here is the code of the call to the News class
/**
* Display the news page
*
* #return Response
*/
public function newsAction()
{
$repositoryNews = $this->getDoctrine()->getRepository('FideliseSignUpBundle:News');
$years = $repositoryNews->getYears();
$news = $repositoryNews->getAll();
return $this->render('#FOSUser/Security/news.html.twig', [
'years' => $years,
'news' => $news
]);
}

Twilio TaskRouter JS SDK not working

According to Twilio Docs I'm trying develop a Call-center Application But The TaskRouter JS
v1.13/taskrouter.min.js
Not supporting as twilio explain in document https://www.twilio.com/docs/taskrouter/js-sdk/worker#reservation-created
worker.on("reservation.created", function(reservation) {
console.log(reservation.task.attributes) // NOT FOUND
console.log(reservation.task.priority) // NOT FOUND
console.log(reservation.task.age) // NOT FOUND
console.log(reservation.task.sid) // NOT FOUND
console.log(reservation.sid) // RETURNS task sid
});
reservation.sid print task sid & If I remove .task It returns respective output related to task But here I expect reservation related output.
Below are twilio client SDK are currently used in my application.
https://media.twiliocdn.com/sdk/js/sync/releases/0.5.10/twilio-sync.js
https://media.twiliocdn.com/sdk/js/client/releases/1.4.31/twilio.min.js
https://media.twiliocdn.com/taskrouter/js/v1.13/taskrouter.min.js
https://media.twiliocdn.com/taskrouter/js/v1.0/taskrouter.worker.min.js
There was two different issue but It related to each other.
First I remove
https://media.twiliocdn.com/taskrouter/js/v1.0/taskrouter.worker.min.js
It fixed
worker.on("reservation.created", function(reservation) {
console.log(reservation.task.attributes) // FOUND
console.log(reservation.task.priority) // FOUND
console.log(reservation.task.age) // FOUND
console.log(reservation.task.sid) // FOUND
console.log(reservation.sid) // RETURNS reservation sid
});
BUT After I remove taskrouter.worker.min.js , I faced another issue (i.e worker event stopped working)
worker.on("ready", function(worker) {
});
Because both version use different key to get event value
/v1.13/taskrouter.min.js for example worker.activityName
/v1.0/taskrouter.worker.min.js for example worker.activity_name
Secondly , I need to update all key according to
/v1.13/taskrouter.min.js in my client side Js
For example, Replace worker.activity_name with updated key worker.activityName according to
v1.13
This resolve all of my issue.

How can I get the Register form on the front page in Drupal 8?

I've been trying to get the create account form (register form) in a pop-up on the front page, without any success.
Can anybody here help me out with an example that works?
I've tried adapting examples from Drupal 7 but couldn't get them to work, I've tried to make a custom form but it didn't work, I've tried installing modules that could handle this but they also didn't work.
The last attempt I've made to resolve this problem was:
<?php
/**
* #file
* Functions to support theming in the themename theme.
*/
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Component\Utility\UrlHelper;
/**
* Implements hook_preprocess_HOOK() for HTML document templates.
*/
function themename_preprocess_html(&$variables) {
$form = \Drupal::formBuilder()->getForm('Drupal\user\register');
return $form;
}
Any help would be greatly appreciated.
Thank you!
you can use this module: https://www.drupal.org/project/formblock which exposes some additional forms as blocks (like the user registration, new password, contact, etc..). So after you install it you can just configure the block to appear only on the front page. The registration block will not be available for authenticated users or if the anonymous users are not allowed to create new accounts.
However, you will also have to apply this patch https://www.drupal.org/node/2570221 (if it will not be already committed by the time you check it) if you use the latest Drupal8 stable version, otherwise you will get a fatal error.
This link explains how it can be used to programmatically render the login and registration forms.
http://web-tricks.org/content/how-render-user-login-form-and-user-register-form-drupal-8
For the login form
$form = Drupal::formBuilder()->getForm(Drupal\user\Form\UserLoginForm::class) ;
$render = Drupal::service('renderer');
$variables['login_form'] = $render->renderPlain($form);
and for register form
$entity = \Drupal::entityTypeManager()->getStorage('user')->create(array());
$formObject = \Drupal::entityTypeManager()
->getFormObject('user', 'register')->setEntity($entity);
$form = \Drupal::formBuilder()->getForm($formObject);
$variables['register_form'] = \Drupal::service('renderer')->render($form);

How to pass variable from Module to Controller in Yii2?

I am building restful stateless API using Yii2... So far so good. Now I failed at rookie problem.
I have decided to make API application (preferred by Yii) and make API as a module. So my structure is:
- modules
-- v1
--- components
--- controllers
--- models
Inside v1 folder of course there is Module.php. In here I do authentication like:
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::className(),
'auth' => function($username, $password) {
... get user's data from DB ...
[HERE]
}
];
and at point [HERE] I sotre user's ID in public variable.
So far so good...
So when I for example call v1/abc/index abc controller loads in inside that controller I would like to access user's ID stored at point [HERE]. Any idea?
To access module from controller, you should simply use $this->module.
And from a view : $this->context->module.
No need to use getModule() here.
Read more : http://www.yiiframework.com/doc-2.0/yii-base-controller.html#$module-detail
PS: to access module outside its controllers/views you could use :
Yii::app()->getModule('module');
Have you tried
$v1Module = Yii::app()->getModule('v1');
And then simply
echo $v1Module->yourPublicVariable;