Zend SharedEventManager attaching custom target - events

I'm playing with SharedEventManager
here is a working portion of code :
public function init(ModuleManager $moduleManager) {
echo("<H1>LISTENER</H1>");
$eventManager = $moduleManager->getEventManager();
$sharedEventManager=$eventManager->getSharedManager();
// attach a listener
$sharedEventManager->attach('*','do', function ($e) {
echo("<H4>Message receveid</H4>");
echo("<p>name={$e->getName()}<p>");
echo("<p>Target {$e->getTarget()}</p>");
echo("<p>param1={$e->getParams()['param1']}</p>");
});
// sending event
// set params
$params = ['param1' => 'value of param1'];
// way 1 : works...
$eventManager->trigger('do', 'CUSTOM_IDENTIFIER', $params);
// way 2 : works too
$event1=new \Zend\EventManager\Event('do', 'CUSTOM_IDENTIFIER', $params);
$eventManager->triggerEvent($event1);
}
and the output is ok :
LISTENER
Message receveid
name=do
Target CUSTOM_IDENTIFIER
param1=value of param1
Message receveid
name=do
Target CUSTOM_IDENTIFIER
param1=value of param1
so...
$sharedEventManager->attach('*','do', function ($e) ...
attach all targets *, for 'do' event name
it works...
A)
$sharedEventManager->attach('CUSTOM_IDENTIFIER','do', function ($e) ...
it doesn't work. ...i mean : no output , the message is not handled,
why ??
B)
$sharedEventManager->attach('CUSTOM_IDENTIFIER','*', function ($e) ...
it doesn't work. ...i mean : no output , the message is not handled,
why ??
Question : it is possible to attach events but only for CUSTOM_IDENTIFIER target without using * ?

Looking at your code, you are mixing Event's target and SharedEventManager's identifiers.
The correct version of your code, with correct names, is:
public function init(ModuleManager $moduleManager) {
echo("<H1>LISTENER</H1>");
$eventManager = $moduleManager->getEventManager();
$sharedEventManager = $eventManager->getSharedManager();
// attach a listener
$identifier = '*'; // Use all identifiers
$eventName = 'do';
$sharedEventManager->attach($identifier, $eventName, function ($e) {
echo '<p>Event received, <b>name:</b> "'.$e->getName().'", <b>Target:</b> '.$e->getTarget().'</p>';
});
// Sending event
$eventManager->trigger('do', 'CUSTOM_TARGET');
$eventManager->triggerEvent(new \Zend\EventManager\Event('do', 'CUSTOM_TARGET_NEW_EVENT'));
}
Which gives the following result:
LISTENER
Event received, name: "do", Target: CUSTOM_TARGET
Event received, name: "do", Target: CUSTOM_TARGET_NEW_EVENT
You must set the identifier to the EventManager, otherwise your CUSTOM_IDENTIFIER won't be used when the event will be triggered.
public function init(ModuleManager $moduleManager) {
echo("<H1>LISTENER</H1>");
$eventManager = $moduleManager->getEventManager();
$sharedEventManager = $eventManager->getSharedManager();
// Attach listener to all identifiers
$identifier = '*'; // Use all identifiers
$eventName = 'do';
$sharedEventManager->attach($identifier, $eventName, function ($e) {
echo '<p>ALL identifier, Event received, <b>name:</b> "'.$e->getName().'", <b>Target:</b> '.$e->getTarget().'</p>';
});
// Attach listener to custom identifier
$customIdentifier = 'MY_CUSTOM_IDENTIFIER'; // Use all identifiers
$sharedEventManager->attach($customIdentifier, $eventName, function ($e) {
echo '<p>Custom identifier, Event received, <b>name:</b> "'.$e->getName().'", <b>Target:</b> '.$e->getTarget().'</p>';
});
// Sending event
$eventManager->trigger('do', 'CUSTOM_TARGET');
$eventManager->triggerEvent(new \Zend\EventManager\Event('do', 'CUSTOM_TARGET_NEW_EVENT'));
$eventManager->addIdentifiers(['MY_CUSTOM_IDENTIFIER']);
$eventManager->trigger('do', 'CUSTOM_TARGET_CUSTOM_IDENTIFIER');
$eventManager->triggerEvent(new \Zend\EventManager\Event('do', 'CUSTOM_TARGET_CUSTOM_IDENTIFIER_NEW_EVENT'));
}
The result is:
LISTENER
ALL identifier, Event received, name: "do", Target: CUSTOM_TARGET
ALL identifier, Event received, name: "do", Target: CUSTOM_TARGET_NEW_EVENT
Custom identifier, Event received, name: "do", Target: CUSTOM_TARGET_CUSTOM_IDENTIFIER
ALL identifier, Event received, name: "do", Target: CUSTOM_TARGET_CUSTOM_IDENTIFIER
Custom identifier, Event received, name: "do", Target: CUSTOM_TARGET_CUSTOM_IDENTIFIER_NEW_EVENT
ALL identifier, Event received, name: "do", Target: CUSTOM_TARGET_CUSTOM_IDENTIFIER_NEW_EVENT
As you can see, the identifier * catches all events (therefore, the 4 lines of ALL identifier), whilst there are only 2 lines for the custom identifier.
Obviously, it'd be better to use a better (and more comprehensible) custom identifier, such as a class name, or an interface.
Hope this will help you

Related

Receiving error: Class Action is missing in schema: actions.actions

I'm trying to broadcast transaction having following actions:
actions: [
transactions.createAccount(),
transactions.transfer(new BN(swapParams.value.toFixed())),
transactions.deployContract(new Uint8Array(bytecode)),
transactions.functionCall(
ABI.init.method,
{
secretHash: Buffer.from(swapParams.secretHash, 'hex').toString('base64'),
expiration: `${toNearTimestampFormat(swapParams.expiration)}`,
buyer: swapParams.recipientAddress
},
new BN(ABI.init.gas),
new BN(0)
)
]
But when I invoke
const tx = await from.signAndSendTransaction(addressToString(options.to), options.actions)
I receive following callstack:
Any idea what might be the reason?
I'm using:
near-js-api: 0.39.0
According to the documentation, source code, and defined types signAndSendTransaction should take a single argument (an object with receiverId and actions fields):
const tx = await from.signAndSendTransaction({
receiverId: addressToString(options.to),
actions: options.actions
})
Was there an example/doc that mislead you, so you arrived with this function call interface? We should fix that.

How to fix laravel no command 'Redis::throttle'?

I just use doc example,but get the error
exception 'Predis\ClientException' with message 'Command 'THROTTLE' is not a registered Redis command.
I havce search a lot about redis command,but nothing about throttle.
public function handle()
{
// Allow only 2 emails every 1 second
Redis::throttle('my-mailtrap')->allow(2)->every(1)->then(function () {
$recipient = 'steven#example.com';
Mail::to($recipient)->send(new OrderShipped($this->order));
Log::info('Emailed order ' . $this->order->id);
}, function () {
// Could not obtain lock; this job will be re-queued
return $this->release(2);
});
}
What should I do?Any help,Thanks!
throttle method is defined in Illuminate/Redis/Connections/PredisConnection.
The Redis facade allows for you to get the connection using
Redis::connection()
->throttle('my-mailtrap')
//...
http://laravel.com/docs/5.8/redis

Testing NGXS states with sub states feeds wrong state into action handler

Setup:
I have a parent state defined as
#State<ParentStateModel>({
name: 'grid',
defaults: {
parentData: 'some data'
},
children: [LoadingState]
})
export class ParentState {
#Action(Action1)
action1(ctx: stateContext<ParentStateModel>, action: Action1) {
// In production this state will be ParentStateModel as expected
// but in unit test, it will be of type LoadingState
const state = ctx.getState();
}
}
And a child state defined as
#State<LoadingStateModel>({
name: 'gridLoading',
defaults: {
loading: false
}
})
export class LoadingState{
#Action(Action1)
action1(ctx: stateContext<LoadingStateModel>, action: Action1) {
ctx.setState({loading: true});
}
}
Notice that both states respond to Action1.
When running this in production, it works as it should. The loading state takes care of the LoadingStateModel and the ParentState takes care of the ParentStateModel.
But when unit testing the code, the action handler in ParentState is fed the LoadingStateModel instead of the ParentStateModel (see comment in code).
My unit test is setup as follows
TestBed.configureTestingModule({
imports: [NgxsModule.forRoot([CashflowState, LoadingState])]
});
If I do not include LoadingState in the imports array, NGXS fails with Child state not found: function LoadingState()
Am I doing something wrong, or is it a bug in NGXS?

How to get Web Bluetooth to send multiple `characteristicvaluechanged` events?

[paraphrasing an IRC conversation]
Trying to build a temperature sensor with ardunio and a DHT11 sensor and a HM10 bluetooth sensor. When getting the temperature values with Web Bluetooth but it doesn't seem to be firing the characteristicvaluechanged event. It only gives the initial value.
document.querySelector('button')
.addEventListener('click', connectBluetooth)
function connectBluetooth() {
navigator.bluetooth
.requestDevice({
optionalServices: [ 0xffe0 ],
acceptAllDevices: true
})
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService(0xffe0))
.then(service => service.getCharacteristic(0xffe1))
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged',
handleValueChanged)
return characteristic.readValue()
})
.catch(err => console.error(err))
}
function handleValueChanged(event) {
console.log('Handling...')
let value = event.target.value.getUint8(0)
console.log(`The value is: ${value}`)
}
You never subscribed to notifications. See https://googlechrome.github.io/samples/web-bluetooth/notifications.html for an example. Registering the event listener is not sufficient, you must also call characteristic.startNotifications(). The readValue was returning one result, so just replace it with startNotifications.

Ratchet WAMP onpublish always publish to all clients include the publish caller or not?

I have just made a chat hello world for the Ratchet WAMP + autobahn version 1.
full source code here if you want to see
The JavaScript client send chat message:
function click_send_btn() {
var json_data = {
"message": $.trim($("#input_message").val())
};
sess.publish("send_message", json_data, true);
}
The PHP Ratchet server publish the message:
public function onPublish(\Ratchet\ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) {
switch ($topic) {
case 'http://localhost/enter_room':
$foundChater = $this->allChater[$conn];
$newChaterName = $event['username'];
$foundChater->setChatName($newChaterName);
break;
case 'send_message':
$foundChater = $this->allChater[$conn];
$event['username']=$foundChater->getChatName();
break;
}
$topic->broadcast($event);
echo "onPublish {$conn->resourceId}\n";
}
I don't understand why publish with excludeme not working.
In the above 2 firefox, right firefox said: I am bar. The message should not display at himself, but it is.
doc ref: autobahn version 1 javascript publish with excludeme
doc ref: ratchet onpublish
doc ref: ratchet topic broadcast
I have just fix it.
What a fool I am. I had not handle the parameter "array $exclude"
and I also used the $topic->broadcast($event) to force broadcast to all.
Now I create a function
/**
* check whitelist and blacklist
*
* #param array of sessionId $exclude -- blacklist
* #param array of sessionId $eligible -- whitelist
* #return array of \Ratchet\ConnectionInterface
*/
private function getPublishFinalList(array $exclude, array $eligible) {
//array of sessionId
$allSessionId = array();
$this->allChater->rewind();
while ($this->allChater->valid()) {
array_push($allSessionId, $this->allChater->current()->WAMP->sessionId);
$this->allChater->next();
}
//if whitelist exist, use whitelist to filter
if (count($eligible) > 0) {
$allSessionId = array_intersect($allSessionId, $eligible);
}
//then if blacklist exist, use blacklist to filter
if (count($exclude) > 0) {
$allSessionId = array_diff($allSessionId, $exclude);
}
//return array of connection
$result = array();
$this->allChater->rewind();
while ($this->allChater->valid()) {
$currentConn = $this->allChater->current();
if (in_array($currentConn->WAMP->sessionId, $allSessionId)) {
array_push($result, $currentConn);
}
$this->allChater->next();
}
return $result;
}
in the onPublish, I not use the $topic->broadcast($event) anymore.
$conn2PublishArray = $this->getPublishFinalList($exclude, $eligible);
foreach ($conn2PublishArray as $conn2Publish) {
$conn2Publish->event($topic, $new_event);
}
connection class has a method 'even', which can send message to the 'subscriber' directly.
Ratchet.Wamp.WampConnection event method

Resources