Ferreteria/v0.6/clade/IO/Aspect/Connx/run/Session/Local/Proc/@code

From WoozleCodes
Jump to navigation Jump to search
Code Snapshots & Removals
interface iProc extends BaseIface {}
class cProc extends BaseClass implements SelfIface {
    use HasRExec;

    // ++ CONFIG ++ //

    public function SType() : string { return 'local process-session'; }
    public function IdentityForLog()  : string { return parent::IdentityForLog() . ' ' . $this->OCommand->AsString; }

    // -- CONFIG -- //
    // ++ STATUS ++ //

    // CEMENT
    public function IsRunning() : bool { return $this->OStatus()->IsRunning(); }

    // -- STATUS -- //
    // ++ ACTION ++ //

    // CEMENT
    protected function StartProcess() {
        $oCmd = $this->OCommand;
        $sCmd = $oCmd->AsString;

        $arConf = array(  // streams configuration for proc_open()
          0 => array("pipe", "r"),  // [0] -> stdin (input to process)
          1 => array("pipe", "w"),  // [1] -> stdout (output from process}
          2 => array("pipe", "w")   // [2] -> stderr (error messages from process)
        );
        $rProc = proc_open($sCmd, $arConf, $arPipes);
        $this->RExec = $rProc;  // save the process-resource
        $oaPipes = $this->OAProcPipes;
        $oaPipes->OARsrcs->SetVals($arPipes);

        $this->AmHere('LOCAL PROCESS STARTED: '.$sCmd);

        $oaPipes->CountOpen();    // 2025-04-12 For now, this is just a diagnostic check: it shows a messsage if any pipe did not open.
        $ok = is_resource($rProc);
        $oAct = new OpCmdClass; // get a new result object
        $oAct->IsOkay = $ok;

        return $oAct;
    }

    // 2026-03-30 This will need some tweaking to work on anything except Local\Proc.
    // 2026-04-03 Moved from base Session to Proc.
    protected function CanalSetup() {
      $this->AmHere('SETUP local Canals');
        $oaPipes = $this->OAProcPipes;
        $oaPipes->Block(FALSE);

        $oCanals = CanalsClass::FromVoid();

        $oProcLecture = $oaPipes->OStream; // Process Lecturer
        $oProcListen = $oaPipes->IStream;  // Process Listener
        $oProcErrors = $oaPipes->EStream;  // Process Errors

        $qoAppLect = $this->QOAppLecturer;
        $qoAppLstn = $this->QOAppListener;
        $qoAppErrs = $this->QOAppErrorBin;

        $oCmdListen = NULL;
        $oCmdLecture = NULL;
        $oCmdErrors = NULL;
        if ($qoAppLstn->HasIt()) {
            $oCmdListen = $qoAppLstn->GetIt();   // Command Listener stream
            $oCanalRecv = ConveyClass::FromPair($oProcLecture,$oCmdListen);
            $oCanals->AddIt($oCanalRecv);
        } else {
            $this->AmHereShort('Application has no listener.');
        }
        if ($qoAppLect->HasIt()) {
            $oCmdLecture = $qoAppLect->GetIt();  // Command Lecturer stream
            $oCanalSend = ConveyClass::FromPair($oCmdLecture,$oProcListen);
            $oCanals->AddIt($oCanalSend);
        #} else {
        #    $this->AmHereShort('No command-lecturer.');
        }
        if ($qoAppErrs->HasIt()) {
            $oCmdErrors = $qoAppErrs->GetIt();    // Command Error-messages stream
            $oCanalErrs = ConveyClass::FromPair($oProcErrors,$oCmdErrors);
            $oCanals->AddIt($oCanalErrs);
        } else {
            $this->AmHereShort('Application has no error-bin.');
        }

        $oCanals->OnEvent(new EventOnReset);  // reset all the streams
        $this->OCanals = $oCanals;
    }

    // -- ACTION -- //
    // ++ OBJECTS ++ //

    protected function OStatus() : StatusIface { return StatusClass::FromProcNative($this->RExec); }

    protected APipesIface $OAProcPipes { get => $this->OAProcPipes ??= new APipesClass; }  // pipes for external process
    protected APipesIface $OACodePipes { get => $this->OACodePipes ??= new APipesClass; }  // pipes from application code

    // ++ OBJECTS: API streams ++ //

    public StreamIface $OExecLecture { get => $this->OAProcPipes->OStream; }
    public StreamIface $OExecRespond { get => $this->OAProcPipes->IStream; } // debugging -- possibly not needed
    public StreamIface $OExecErrsBin { get => $this->OAProcPipes->EStream; }

    // -- OBJECTS -- //
    // ++ LIFECYCLE ++ //

    public function ActualOpen() : OpOpenIface { return OpOpenClass::AsOkay(); }
    public function ActualShut() : OpShutIface {
        // close the pipes:
        $oaPipes = $this->OAProcPipes;
        $oaPipes->Shut();
        // this must be *after* pipes are closed, to prevent deadlock:
        $nStatus = proc_close($this->RExec);
        $oAct = $this->OpShut();
        $oAct->IsOkay = ($nStatus !== -1);

        return $oAct;
    }

    // -- LIFECYCLE -- //
    // ++ DIAGS ++ //

    public function VIEW_Inline() : string {
        return $this->DIAG_ObjIDStr().' PROCESS: ['.$this->OStatus()->VIEW_Inline().'] STREAMS: ['.$this->OAProcPipes->VIEW_Inline().']';
    }
    public function VIEW_AsBlock() : string {
        return '++PROCESS STATUS:'
          .CRLF.$this->OStatus()->DEBUG_AsBlock()
          .CRLF.'++PROCESS STREAMS:'
          .CRLF.$this->OAProcPipes->DEBUG_AsBlock()
          .CRLF;
    }

    // ++ DIAGS ++ //
}