Timer mit eigenen Daten



Timer können auch eigene Daten transportieren

In diesem Beispiel wollen wir eigene Daten mit einem Timer transportieren. Das kann zum Beispiel erforderlich sein, wenn Daten zeit-versetzt verarbeitet werden sollen. Dann gibt man den Timern die zu bearbeitenden Daten mit und muss sie nicht anderweitig speichern. So könnten mehrere Aufgaben parallel verarbeitet werden,

Um eigene Daten transportieren zu können, werden dem Timer die Daten in einem Record mitgeben. Wir definieren erst mal diesen Record:

<record id="8f68d229-6d16-42a0-b454-dcb40dadbb52" name="TIMER_TARGET_014">
    
    <description>
        A Timer for Target014 with data
    </description>
    
    <slot keyid="" keytype="1" name="WORK" type="STRING" direction="REQUEST">
        <description>A Path.</description>
    </slot>
    
</record>

In dem Beispiel transportiert der Timer einen String, z.B. einen Dateipfad.

Um die zeitversetzte Bearbeitung mehrerer Workloads zu demonstrieren, erstellen wir gleich zwei Timer mit unterschiedlichen Daten ("0" und "1"). Die "Arbeit" besteht dann darin, weitere Ziffern an den String zu hängen und dann die Strings zu loggen. Der Output ist schön im LOG zu verfolgen.

final class CTarget014 extends CTarget
{
    private static final long TIMEOUT1 = 6000L;
    private static final long TIMEOUT2 = 10000L;
    private static final int MAXDIGIT = 9;

    CTarget014()
    {
        addMessageHandler(CRecordStartTarget.ID, new IMessageHandler()
        {
            @Override
            public boolean handleMessage(final CEnvelope aEnvelope,
                                         final CRecord aRecord) throws Exception
            {
                startTimer("0", TIMEOUT1);
                startTimer("1", TIMEOUT2);

                aEnvelope.setResult(null);
                return true;
            }

        });

        addMessageHandler(CRecordTimerTarget014.ID, new IMessageHandler()
        {
            @Override
            public boolean handleMessage(final CEnvelope aEnvelope,
                                         final CRecord aRecord) throws Exception
            {
                String work = CRecordTimerTarget014.getParamWork(aRecord, "");
                final long timeout = CRecordTimer.getParamTimeout(aRecord, 0);

                // do our work
                work = work + CUtilRandom.getRandom().nextInt(MAXDIGIT);
                CConstants.LOG.trace("work Node001Example002Target014={}", work);

                startTimer(work, timeout);

                aEnvelope.setResult(null);
                return true;
            }

        });
    }

    protected void startTimer(final String aWork,
                              final long aTimeout) throws CException
    {
        // create a record with the ID CRecordTimerTarget014.ID
        final CRecord timerRecord = CRecordTimerTarget014.create();

        // put our work into the timer record
        CRecordTimerTarget014.setParamWork(timerRecord, aWork);

        // we start a timer and will get a timer message AFTER aTimeout milliseconds
        // The timer will STOP after one message
        getTimerManager().startTimer(CRecordTimerTarget014.ID, getAddress(), aTimeout, false, timerRecord);
    }
}

Es wurden zwei Timer mit unterschiedlichen Daten und verschiedenen Timeouts gestartet. Die Daten werden in einem Record als letztem Argument der startTimer()-Methode mitgegeben. Wenn im MessageHandler ein Breakpoint gesetzt wird, kann im Record neben den Strings auch noch die Timer-Daten beobachtet werden (siehe vorhergehendes Beispiel). Der veränderte String wird dann einem neuen Timer als Payload mitgegeben.

Sequence Monitor

Im Sequenz-Monitor sehen wir, wie die Timer mit unterschiedlichen Timeouts auftreten. Die Strings werden immer länger. Neben den Strings können wir auch die Timer-Daten erkennen.

Diese Beispiele findest du im Projekt D1ExamplesNode001 im package de.softdevel.d1.examples.node001.example002.