Select to view content in your preferred language

Heartbeat thread restarts custom Transport on RunningState.ERROR or RunningState.STOPPED

4460
3
Jump to solution
10-26-2015 11:11 AM
JacobHays1
Emerging Contributor

I have a custom GeoEvent transport that is getting automatically restarted when the transport code sets the RunningState to ERROR or STOPPED.  This results in the transport making successive passes through the code, when ideally the transport (and associated connector) should cease execution so the end user can resolve the error condition.

I have not been able to find any documentation related to "Heartbeat Thread".  The only place I see mention of "Heartbeat Thread" is in the karaf.log file, which in turn is calling the Start() method of my transport.  I'm wondering how to prevent that heartbeat from restarting the transport.

The following example illustrates the problem, here I have intentionally fed in bad authentication parameters (the transport interacts with a SOAP web service).  RunningState is set to ERROR, where it should stay through the rest of execution, however it is restarted by that Heartbeat Thread.  I have also tried stopping the transport after this example error, in that case the the stop() method is executed, but the transport is still restarted by the heartbeat.

Environment:

Windows Server 2012

ArcGIS Server 10.3.0  (10.3.4322)

GeoEvent Extension 10.3.0  (10.3.4322)

Karaf.log

2015-10-26 11:06:13,541 | ERROR | ansport Listener | TestInboundTransport             | ort.inbound.TestInboundTransport  357 | 370 - com.test.arcgis.geoevent.transport.inbound.TestInboundTransport - 10.3.0 | Authentication to Test web services failed!  Error: Access Denied.

2015-10-26 11:06:18,460 | INFO  | Heartbeat Thread | TestInboundTransport             | ort.inbound.TestInboundTransport  409 | 370 - com.test.arcgis.geoevent.transport.inbound.TestInboundTransport - 10.3.0 | Test Inbound Transport Service Starting

Code Snippets

.. The error entry…

if( ((AuthSoapHeader)holder.value).getError() != null)

      {

            log.error("Authentication to Test web services failed!  Error: " + ((AuthSoapHeader)holder.value).getError());

            //TODO: clean up and stop service

            this.setRunningState(RunningState.ERROR);

            //this.stop();

            return null;

      }

@SuppressWarnings("incomplete-switch")

public synchronized void start() throws RunningException

{

     log.info("Test Inbound Transport Service Starting");

     switch (getRunningState())

     {

            case STARTING:

            case STARTED:

                  return;  //added to prevent multiple thread starts

            case STOPPING:

                  return;

     }

     //this.serviceStopping = false;

     this.setRunningState(RunningState.STARTING);

     this.thread = new Thread(null, this, "Test Inbound Transport Listener");

     this.thread.start();

}

           

public synchronized void stop()    

{

      this.setRunningState(RunningState.STOPPING);

      log.info("Test Inbound Transport Service Stopping");

      cleanup();

      this.setRunningState(RunningState.STOPPED);

      super.stop();

}

private void cleanup()

{

      if( this.byteBuffer != null)

      {

            this.byteBuffer.clear();

      }

}

0 Kudos
1 Solution

Accepted Solutions
MingZhao
Occasional Contributor

What you can do is, in your start() method of the transport, you will just return if the current running state is ERROR.  That way you will not attempt to start it again.

View solution in original post

3 Replies
MingZhao
Occasional Contributor

What you can do is, in your start() method of the transport, you will just return if the current running state is ERROR.  That way you will not attempt to start it again.

JacobHays1
Emerging Contributor

Thank you Ming,

That is actually what I ended up doing, just forgot to update this thread.

On a somewhat related note, and likely due to how my polling mechanism works, I also added an explicit check for thread.isAlive and interrupt that thread in my stop() method.  This halts the execution of the child thread so it does not get picked up by the heartbeat and restarted again or potentially become a zombie thread once the transport is started again.

0 Kudos
JerryStafurik
Emerging Contributor

Are there any updates on this?  Is it possible to programmatically completely stop a transport/connector?  I've got a use case where I need to start a connector manually, load some data, and stop the connector once everything is loaded.  I'm porting a connector to 10.5.1 from 10.2.2 -- where this was possible.  I don't want the heartbeat service constantly trying to restart the connector.  Also, putting the connector into an Error state is not correct in this case, if there are no errors on data load.  I need the status to be Stopped.

0 Kudos