We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 22295
    • 153 Posts
    I am using modRegister as a message queue for various things (comment notifications, mailchimp sync, email change validation, etc..)
    it works good and simple, and I must say it’s quite nice to have a mq built in modx.

    I handle the register/unregister and the event handling itself in the models, and there’s a simple execution script (time-based cron’ed) that simply queries the queue.
    About the queue read - everything (almost) works well, but something is a bit strange with the timing logic.

    a. there’s an unknown delay (10-60s??) between the time messages are in the queue (i see in the mysql table) until the register read actually can pick them up.
    I then refresh 2-3 times (or just wait a min..) - then register reads them.. any clue why? I am sure about this issue, as I see it all around, doesn’t matter in which model.
    note: when i un-register a message and check - the read has no time gap. strange.


    b. timing: for example with $options[’time_limit’] = 30; $options[’msg_limit’] = 10;
    1. if the queue is empty it’ll just hang for 30sec (as expected), but it does NOT pick up any messages during that time, as it should
    2. if the queue is not empty - it’ll process it and quit (without waiting 30s) even if the queue contains only 2 messages (ie. not reaching the msg_limit)
    I’ve played around with this and digged in the source code, the safest option i found until now was to do a $options[’poll_limit’] = 1 (as opposed to 0 - unlimited) to force only one pass and cron this script every 2 min...
    I haven’t seen any sample use anywhere which actually uses the time_limit and poll_interval, in the core - it’s always a single pass.

    c. On some scripts I use the ’remove_read’ = false, as I want to control this based on the returned result (for example, in case the mail server is down, i’d retry it later)
    As I use the above single-pass-fast-cron: I want to be sure this script does not execute in parallel (to avoid duplicates). can this be enforced (ie. similar to resource lock)?



    here’s a sample small script:
    require_once MODX_CORE_PATH.'components/activityStream/model/activityStream/activityStream.class.php';
    $modx->activityStream = new ActivityStream($modx);
    
    $options = array();
    $options['msg_limit'] =  20 ;
    //$options['time_limit'] = 30;
    //$options['poll_interval'] = 1;
    $options['poll_limit'] = 1;
    $options['remove_read'] = false;
    
    $modx->getService('registry', 'registry.modRegistry');
    $modx->registry->addRegister($modx->activityStream->mqRegister,'registry.modDbRegister');
    $modx->registry->notification->connect();
    $modx->registry->notification->subscribe($modx->activityStream->mqTopic);
    $msgs = $modx->registry->notification->read($options);
    
    if (empty($msgs)) exit();
    $output = array();
    	foreach ($msgs as $msg) {
    		if (!empty($msg)) {
    			$ret = $modx->activityStream->eventNotification($msg);	// Handle the event and return status
    			if ($ret) {	// OK?   REMOVE_READ MESSAGES FROM MQ
    				$output[] = date("H:i:s") . " : SUCCESS $ret ($msg)";
    				$topicObj = $modx->getObject('registry.db.modDbRegisterTopic', array('name' => $modx->activityStream->mqTopic));	// get topicObj (to convert from  name --> id)
    				$modx->removeObject('modDbRegisterMessage', array('topic' => $topicObj->get('id'), 'id' => $modx->activityStream->mqIdPrefix . $msg));	// remove message from mq
    			}
    			else {	// ERROR
    				$output[] = date("H:i:s") ." : ERROR $ret ($msg)";
    			}
    		}
    	}
    var_dump($output);
    

      • 22295
      • 153 Posts
      btw, just for future searchers
      for cron (or simply running stuff via php and not the web server)
      add this to the begining of your php:



      // MANUALLY SUPPLIED if THIS IS RUN VIA CRON AND NOT THE WEB SERVER
      if (empty($_SERVER['SERVER_PORT'])) $_SERVER['SERVER_PORT'] = 80; 
      if (empty($_SERVER['HTTP_HOST'])) $_SERVER['HTTP_HOST'] = 'yourdom.com';
      $_REQUEST['ctx'] = 'web';
      
      /* modx object */
      require_once dirname(dirname(dirname(dirname(__FILE__)))).'/config.core.php';
      require_once MODX_CORE_PATH.'config/'.MODX_CONFIG_KEY.'.inc.php';
      require_once MODX_CONNECTORS_PATH.'index.php';
        • 22303 MODX Staff
        • 10,725 Posts
        I mostly included the timed and continuous polling options for fun; I really don’t ever recommend running a PHP process as a daemon, but you can if you do it carefully. Regardless, I’ll try and setup some tests for this and see if I can reproduce what you are describing, but I think you just have your poll_interval set as long or longer than your time_limit.

        BTW, there will be more CLI support in the future, but right now, this changes behavior because a lot of MODx internals are dependent on user sessions and $_SESSION is not available in CLI either. So security is wide-open when running in CLI, and certain features may break. BTW, all you really need to include/use MODx in CLI is:
        <?php
        include('/path/to/a/config.core.php');
        include(MODX_CORE_PATH . 'model/modx/modx.class.php');
        $modx = new modX();
        $modx->initialize('somecontext');
        ?>

          • 22295
          • 153 Posts
          Thanks for your reply.

          The polling is actually not so important.
          question (a) has more priority as it can cause end-user issues, for example:
          Change Email procedure goes like this:
          a. user sets a new email
          b. conformation email is sent to him (and a validation request is registered in the queue)
          c. user goes to him email inbox and clicks the validation link (which reads the queue)

          If he does it fast (between (b) and (c)) he will get an error on the validation simply because the queue read doesn’t return the message. if he’ll wait a minute and refresh - it’ll work.
          This procedure is the same style as you register-activation procedure.
          On notification queues it’s no big deal, as it’ll be picked up with a min. delay.. but end-user errors are ugly.


          I am pretty sure about this read() problem, as I see it everywhere i use modRegister.
          and the time is not fixed (more or less 10-40 sec from the time the message is in the queue until read() actually can read it)


          Thanks again.
            • 22295
            • 153 Posts
            addendum:

            I have two-three processors that manage resources (edit/delete/etc..), and I have wierd random resource locking issues (where a resource is still locked, after I removeLock).
            after digging, changing code, caching, etc.. I realized it is the same issue as above - as removeLock uses modRegister (modresource.class.php:446)
            Sometimes it picks up the lock-message from the queue and works well, and sometime not...

            So this ->read()time delay is everywhere...


            Looking at the modRegister code, I couldn’t find a clue for what causes this.
            Any idea?
              • 22303 MODX Staff
              • 10,725 Posts
              Quote from: oori at Apr 08, 2010, 07:42 AM

              So this ->read()time delay is everywhere...

              Looking at the modRegister code, I couldn’t find a clue for what causes this.
              Any idea?
              I will look into as soon as possible. In the meantime, can you open a JIRA ticket for this issue?
                • 22295
                • 153 Posts
                Thanks for your reply.
                http://svn.modxcms.com/jira/browse/MODX-1851

                Please let me know if you can not trace the issue in your environment - I would be happy to assist.