How to execute functions asynchronously with SWOOLE? - swoole

I have heard promising words about php's Swoole project. However, in their doc/examples, I only see the implementation of server handlings (i.e. how to setup webserver, answer requests, etc..). However, I was unable to find examples, how to simply fire an asynchronous functions from cli (i.e. php myfile.php)
where myfile.php might contain (with my undestranding) something like this Swoole\SomeAsyncFunion (just phseudo name):
Swoole\SomeAsyncFunion( function(){ file_get_contents("http://site-1.com"); echo "hello"; } );
Swoole\SomeAsyncFunion( function(){ do_long_running_function(); echo "world"; } );
Swoole\SomeAsyncFunion( .... );
Swoole\SomeAsyncFunion( .... );
Swoole\SomeAsyncFunion( .... );
So, just execute multiple functions in async from php-cli. How to do that? With parallel extension I exactly same as described ( \parallel\run( function(){ ... } ); ) but couldn't figure-out how to do with swoole. (i dont have a requirement of any web-server, just need cli).

you can use Co\run and go
use function Swoole\Coroutine\go;
use function Swoole\Coroutine\run;
run(function () {
go(function () {
file_get_contents("http://site-1.com"); echo "hello";
});
go(function () {
do_long_running_function(); echo "world";
});
});

Related

Dump SNMP information into file using Nagios

Is there any plugin of Nagios which can capture information from multiple SNMP agents and will dump snmpwalk information in a certain interval .
It will be better if information will be dumped in JSON format .
Because of the well documented plugin development guidelines, this is something you could easily build yourself!
Let's build one right now. Let's say we have 2 IP addresses, 192.168.1.10 and 192.168.1.11. We'll build a simple plugin using PHP, although you can ideally write it in any language you like.
This plugin isn't going to conform completely to the guides, but it should give you a nice starting point!
#!/usr/bin/php
<?php
// check if we have at least the minimum required output
// (we need at least 1 argument)
if (count($argv) < 2) {
echo <<<USAGE
Usage:
{$argv[0]} <outputfile> <address1>,<snmpcommunity1>,<snmpversion1>,<mib1> <address2>,<snmpcommunity2>,<snmpversion2>,<mib2> ...
USAGE;
exit(1);
}
// prep the data
$hosts = array();
$output = array();
$output_file = '';
for ($i = 1; $i < count($argv); $i++) {
$host = explode(",", $argv[$i]);
// we need exactly 4 elements
if (count($host) != 4) {
// unless of course we are specifying the output file to write the data to!
if (count($host) == 1) {
$output_file = $argv[$i];
continue;
}
echo "{$argv[$i]} IS INVALID. YOU MUST SPECIFY ALL OF: <address>,<snmpcommunity>,<snmpversion>,<mib>\n";
exit(1);
}
$hosts[] = array(
'address' => $host[0],
'snmp_community' => $host[1],
'snmp_version' => $host[2],
'mib' => $host[3],
);
}
// cycle through each host and gather the data
// this may take a while
foreach($hosts as $host) {
$snmpwalk_array = get_snmpwalk_lines($host['address'], $host['snmp_community'], $host['snmp_version'], $host['mib']);
$snmp_array = walk_lines_to_snmp_array($snmpwalk_array);
$output[$host['address']] = $snmp_array;
}
// convert the output array to json and put it in the file!
$json = json_encode($output);
file_put_contents($output_file, $json);
$num_hosts = count($hosts);
echo "OK - {$num_hosts} PROCESSED\n";
exit(0);
// format an array in a sane way from snmp walk output
// this will return an array like:
// [oid][type] = 'Counter32'
// [oid][value] = 0011232
// etc.
function walk_lines_to_snmp_array($walk_arr) {
$snmp = array();
foreach ($walk_arr as $line) {
$oid = convert_snmpwalk_line_to_array($line, $arr);
if ($oid !== false)
$snmp[$oid] = $arr;
}
return $snmp;
}
// return an array of an executed snmpwalk output
function get_snmpwalk_lines($address, $snmp_community, $snmp_version, $mib) {
$cmd = "snmpwalk -c {$snmp_community} -v {$snmp_version} {$address} -m {$mib}";
exec($cmd, $output);
return $output;
}
// return the oid and pass the array by ref
// or return false on failure
function convert_snmpwalk_line_to_array($line, &$arr) {
if (preg_match('/(.*) = (.*): (.*)/', $line, $matches) === 1) {
$arr = array(
'type' => $matches[2],
'value' => $matches[3],
);
return $matches[1];
}
return false;
}
Now, you can put this in a file in your $USER1$ directory (/usr/local/nagios/libexec) named check_multi_snmpwalk.php and make sure it's executable chmod +x /usr/local/nagios/libexec/check_multi_snmpwalk.php.
Finally, all we need to do is define a command for Nagios to pick it up and use it! Something like the following should suffice:
define command {
command_name check_multi_snmpwalk
command_line $USER1$/check_multi_snmpwalk.php $ARG1$ $ARG2$ $ARG3$ $ARG4$
}
Now you should be able to specify the file you want the JSON to be output to in ARG1, and then each other argument needs to contain the host address, the snmp community, the snmp version and the mib you want to walk.
So, for example:
define service {
host_name localhost
service_description Multi SNMP Walk
use local-service
check_command check_multi_snmpwalk!/tmp/jsonfile!192.168.1.10,community,1,all!192.168.1.11,community,2c,all!!
register 1
}
Now you're saying "Okay, thats all great, but what does it do?!"
I'm glad you asked! This is what it does:
Grabbing some input from the user (what are we snmp walking?)
Executing an snmpwalk (and saving the output) for each host specified
Converting the snmpwalk output to an easy-to-read array
Aggregating each host's snmpwalk easy-to-read array into a giant array
Converting the giant array to JSON
Writing the JSON to the file specified
Returning an OK Status for Nagios with a message stating how many hosts we processed!
A few notes:
This plugin will take a while to run no matter how many hosts you specify, so you may want to consider running it from a cron job instead of a Nagios check
This plugin does NOT conform to the plugin guidelines I linked to earlier, but it was still a fun little project
Hope this helped!

How To Subscribe multiple Publications in meteor without waiting for each other and not using unblock package?

How To Subscribe multiple Publications in meteor without waiting for each other and not using unblock package??
You can register one publish function and return array of cursors:
Meteor.publish('yourPublications', function () {
return [yourPublication1Data, yourPublication2Data, yourPublicationData3];
});
And subscribe only once:
Meteor.subscribe('yourPublications');
You can add this.unblock(); in your publication to unblock:
Meteor.publish('yourPublications1', function() {
this.unblock();
return yourPublication1Data;
}
Meteor.publish('yourPublications2', function() {
this.unblock();
return yourPublication2Data;
}
Meteor.publish('yourPublications3', function() {
this.unblock();
return yourPublicationData3;
}
Then you can subscribe these publication on route or template render.
Meteor.subscribe('yourPublications1');
Meteor.subscribe('yourPublications2');
Meteor.subscribe('yourPublications3');
I am afraid you will need the package or code the same thing like the package does, yourself. I just installed lamhieu:unblock and it works great. But I don't fully understand what it is doing - that code is a bit high level for me.

How to use reactive vars on server side

I want to use a reactive counter var on server side. But I can not guess how to do it without using collections.
I expect {{count}} will be updated after server count var changed without refresh a page or how to send a client that the count was changed?
<body>
{{> test }}
</body>
<template name="test">
{{count}}
</template>
client:
Meteor.call('count', function(err, result) {
console.log(result)
Session.set('count', result)
})
Template.test.helpers({
count: function () {
return Session.get('count')
}
});
server:
var count=0
Meteor.startup(function () {
Meteor.setInterval(function() {
count++
}, 1000)
});
Meteor.methods({
count: function() {
return count
}
})
My code on MeteorPad
I want to see what I expect:
Client:
Meteor.subscribe('count')
Template.test.helpers({
count: function () {
return Counter.findOne().count
}
});
Common:
Counter = new Mongo.Collection('count')
Server:
Meteor.publish('count', function() {
return Counter.find()
})
Meteor.startup(function () {
if(Counter.find().count() === 0) {
Counter.insert({count: 0})
}
Meteor.setInterval(function() {
Counter.update({}, {$inc: {count: 1}})
}, 1000)
});
Example on meteorpad
It depends on how you plan to scale your application. If you plan to scale to multiple server instances then you cannot rely on the servers sharing information automatically. In this case it would be best to create a collection named something like "ApplicationState". Then every instance of your application can use a consistent state, and you can make use of the built in subscriptions.
If you plan to only use a single server instance then you should checkout the documentation on Tracker: http://manual.meteor.com/#tracker. This allows you to defined custom dependencies on data. I have not had the chance to play with it yet, but I am pretty sure that you can create something similar to subscriptions: http://manual.meteor.com/#deps-creatingreactivevalues
Your code does not work as the way you want it because regular plain vars are not reactive data sources. The docs has a list of reactive data sources here http://docs.meteor.com/#/full/reactivity - So for your example to work you'd want to use Session or ReactiveVar - but these only works on the client so they wont help you here.
Your best bet is to create a manual publish function and subscribe to it from the client (or as other people has proposed, use a Collection - which would work across multiple servers as well). Hope that helps!

WordPress - AJAX call returns 0

I am developing a WordPress plugin, and everything works fine. Only problem is, I have an ajax call in jQuery to some code in a php file. It works but it is just a few php commands in a file. That is bad practice in WP, everything should be in a function and attached using a hook.
this is the code in output.php
if(isset($_POST['test']) && $_POST['test'] == 'ON'){
if(isset($_POST['id'])){
$productId = intval(preg_replace('/[^0-9]+/', "", $_POST['id']));
if ($productId > 1){
$results = get_option( 'test_options' );
$result = $results[$productId];
unset($results);
echo json_encode($result);
die();
}
}
}
this is the AJAX-call in jQuery script
$.ajax({
type: "POST",
url: "output.php",
data: {
'test' : "ON",
'id' : productId
},
success: function(results) {
result = $.parseJSON(results);
createArray(result);
}
});
This works fine. But when I change the code in output.php into a function and use action hook like this:
function getInfo(){
$test = $_POST['test']);
$id = $_POST['id']);
if(isset($test) && ($test == "ON")){
$result = '';
if(isset($id)){
if ($id > 1){
$results = get_option( 'test_options' );
$result = $results[$id];
echo json_encode($result);
die();
}
}
}
}
add_action('wp_ajax_getInfo','getInfo');
add_action('wp_ajax_nopriv_getInfo','getInfo');
and change the jQuery script to:
$.ajax({
url: my_ajax_script.ajaxurl,
type: 'POST',
data: {
action : 'getInfo',
test : "ON",
id : productId
},
cache: false,
success: function(results) {
result = $.parseJSON(results);
console.log(result);
alert("succes");
createArray(result);
}
});
it doesn't work. What am I missing? I have checked a lot of questions on stackoverflow describing sort of the same problem, checked the solutions but can't find where I go wrong.
It finally started working once I added the code of the output.php file to the file that held the wp_localize_script() command for the AJAX url.
For frontend use of AJAX calls you need this command to make AJAX available. In admin area AJAX is available by default.

WordPress Process $_POST Inside Parse Request

I'm writing an application to receive and process an Instant Payment Notification message in wordpress. It is a POST request made to a "virtual" url with rewrite rules. The problem however is that only GET vars are acessible, I cannot access the post variable:
Both:
print_r($wp->query_vars['ccustfirstname']);
print_r($_POST);
Result in an empty array
I've modified existing code to match my case:
function ao_add_rewrite_rule() {
print_r($_REQUEST);
$ipn_parameters=array("ccustfullname","ccustfirstname", ... );
foreach ($ipn_parameters as $key => $value) {
add_rewrite_tag("%$value%",".");
}
add_rewrite_tag("%arevico_api%",".","");
add_rewrite_rule( 'ipn', 'index.php?&arevico_api=ipn', 'top');
add_rewrite_rule( 'hoplink', 'index.php?&arevico_api=hop', 'top');
add_rewrite_rule( 'pay', 'index.php?&arevico_api=pay', 'top');
flush_rewrite_rules();//TODO: call only when needed
}
add_action( 'parse_request', 'wpse9870_parse_request' );
function wpse9870_parse_request( &$wp )
{
if (!empty($wp->query_vars['arevico_api'])) {
switch ($wp->query_vars['arevico_api']){
case "ipn":
print_r($wp->query_vars['ccustfirstname']);
print_r($_POST);
die();
// require_once(AREVICO_PLG_BP . "ipn.php");
// $ArevicoIPN=new ArevicoIPN();
break ;
default:
break;
}
}
return;
}
Please note that the arevico_api get parameter does get trough, but the POST parameters don't. I'm testing the application by sending a sample post data trough Simple Rest Client for chrome. How do I get to access thhe post parameters

Resources