簡體   English   中英

Amazon AWS Simple Workflow Service SWF PHP示例

[英]Amazon AWS Simple Workflow Service SWF PHP Samples

我想知道是否有可用於AWS PHPSDK 2+的SWF工作流PHP示例代碼?

我找了一個教程,卻找不到一個。 最后,我使用Ruby和Web API完成了文檔和示例,並拼湊了使用PHP SDK的基本要點。

您需要做的第一件事是注冊您的域,工作流和活動。 這可以通過AWS控制台或使用PHP SDK完成。 使用SDK,使用以下內容:

<?php

require_once "path/to/aws.phar";

use Aws\Swf\SwfClient;

// Create an instance of the SWF class
$client = SwfClient::factory(array(
    "key" => "your_aws_key",
    "secret" => "your_aws_secret_key",
    "region" => "your_aws_region"
));

// Register your domain
$client->registerDomain(array(
    "name" => "domain name you want",
    "description" => "this is a test domain",
    "workflowExecutionRetentionPeriodInDays" => "7"
));

// Register your workflow
$client->registerWorkflowType(array(
    "domain" => "domain name you registered in previous call",
    "name" => "workflow name you want",
    "version" => "1.0",
    "description" => "this is a sample",
    "defaultTaskList" => array(
        "name" => "mainTaskList"
    ),
    "defaultChildPolicy" => "TERMINATE"
));

// Register an activity
$client->registerActivityType(array(
    "domain" => "domain name you registered above",
    "name" => "activity name you want",
    "version" => "1.0",
    "description" => "first activity in our workflow",
    "defaultTaskList" => array(
        "name" => "mainTaskList"
    )
));

// Follow activity registration example above and register 
// more activities as you wish

下一步是創建一個決策者。 這是充當活動(工作者)節點的協調節點的腳本。

// Ask SWF for things the decider needs to know
$result = $client->pollForDecisionTask(array(
    "domain" => "your domain name",
    "taskList" => array(
        "name" => "mainTaskList"
    ),
    "identify" => "default",
    "maximumPageSize" => 50,
    "reverseOrder" => true
));

// Current version of activity types we are using
$activity_type_version = "1.0";

// Parse info we need returned from the pollForDecisionTask call
$task_token = $result["taskToken"];
$workflow_id = $result["workflowExecution"]["workflowId"];
$run_id = $result["workflowExecution"]["runId"];
$last_event = $result["events"][0]["eventId"];

// Our logic that decides what happens next
if($last_event == "3"){
    $activity_type_name = "activity to start if last event ID was 3";
    $task_list = "mainTaskList";
    $activity_id = "1";
    $continue_workflow = true;
}
elseif($last_event == "8"){
    $activity_type_name = "activity to start if last event ID was 8";
    $task_list = "mainTaskList";
    $activity_id = "2";
    $continue_workflow = false;
}

// Now that we populated our variables based on what we received 
// from SWF, we need to tell SWF what we want to do next
if($continue_workflow === true){
    $client->respondDecisionTaskCompleted(array(
        "taskToken" => $task_token,
        "decisions" => array(
            array(
                "decisionType" => "ScheduleActivityTask",
                "scheduleActivityTaskDecisionAttributes" => array(
                    "activityType" => array(
                        "name" => $activity_type_name,
                        "version" => $activity_type_version
                    ),
                    "activityId" => $activity_id,
                    "control" => "this is a sample message",
                    // Customize timeout values
                    "scheduleToCloseTimeout" => "360",
                    "scheduleToStartTimeout" => "300",
                    "startToCloseTimeout" => "60",
                    "heartbeatTimeout" => "60",
                    "taskList" => array(
                        "name" => $task_list
                    ),
                    "input" => "this is a sample message"
                )
            )
        )
    ));
}
// End workflow if last event ID was 8
else if($continue_workflow === false){
    $client->respondDecisionTaskCompleted(array(
        "taskToken" => $task_token,
        "decisions" => array(
            array(
                "decisionType" => "CompleteWorkflowExecution"
            )
        )
    ));
}

最后一步是創建您的活動工作者。 您可以使用以下格式旋轉它們:

// Check with SWF for activities
$result = $client->pollForActivityTask(array(
    "domain" => "domain name you registered",
    "taskList" => array(
        "name" => "mainTaskList"
    )
));

// Take out task token from the response above
$task_token = $result["taskToken"];

// Do things on the computer that this script is saved on
exec("my program i want to execute");

// Tell SWF that we finished what we need to do on this node
$client->respondActivityTaskCompleted(array(
    "taskToken" => $task_token,
    "result" => "I've finished!"
));

您的活動工作者和決策者的腳本可以放在任何服務器上。 這些腳本都調用SWF以便相互通信。

最后,要啟動剛剛創建的工作流程,請使用:

// Generate a random workflow ID
$workflowId = mt_rand(1000, 9999);

// Starts a new instance of our workflow
$client->startWorkflowExecution(array(
    "domain" => "your domain name",
    "workflowId" => $workflowId,
    "workflowType" => array(
        "name" => "your workflow name",
        "version" => "1.0"
    ),
    "taskList" => array(
        "name" => "mainTaskList"
    ),
    "input" => "a message goes here",
    "executionStartToCloseTimeout" => "300",
    'taskStartToCloseTimeout' => "300",
    "childPolicy" => "TERMINATE"
));

基於上面的帖子,我能夠創建一個功能齊全的工作流程,非常容易為您的目的進行修改。謝謝你們。 在使用composer安裝AWS PHP SDK之后,在控制台中分配正確的文件路徑,設置域,工作流類型和活動類型(這非常簡單),您可以使用下面的腳本按順序執行流程。 在發布之前我能夠自己執行它們。 一切設置完成后運行ExecuteFlow.php應該是所有必需的!

這里發布了8個腳本(不用擔心,3個很短):

ExecuteFlow.php:

<?php 
//This script is used to begin a new workflow then activate the decider and workers to finish the job.
// 
//SWF scripts originally developed by ~ in April, 2018 based on the first comment in https://stackoverflow.com/questions/22765377/amazon-aws-simple-workflow-service-swf-php-samples
//
//PROGRAMMER MODIFICATIONS sections are for updates to the Steps in Workflow, the rest of SWF Workflow should be automated with these scripts.
//
// Command Reference: 
//
// https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-swf-2012-01-25.html 
//
// For Reference: 
//          Workflow Type (Name) is MainWorkflow
//          Activity Type (Names) are Step 1, Step 2, and Step 3
//    Task List for MainWorkflow is MainTaskList
//           Task List for Step 1 is TaskList1, Step 2 is TaskList2, etc.
//
//
//Software Required:
//
//Installed AWS PHP SDK
//ExecuteFlow.php
//Decider.php
//Worker.php
//DescribeExecution.php
//TerminateFlow.php
//Test.php
//Test2.php
//Test3.php



//Once it's installed using composer, this accesses the PHP AWS SDK
require_once "PHP-AWS-SDK/autoload.php";


//This grabs the client from the SDK so we can use it to do our SWF bidding.
//(Note: the version should stay synonymous with the currently packaged SDK version so it works with our code.)
$client = new Aws\Swf\SwfClient([
    'version' => '2012-01-25',
    'region'  => 'us-east-1' 
    ]);



//------------------------------------------------------------------------------
//----------------------PROGRAMMER MODIFICATIONS--------------------------------
//------------------------------------------------------------------------------

//Variables that we want to carry through the workflow
$Domain_Name='MyDomainName';
$Activity_Type_Version = "1";
$Workflow_Task_List_Name="MainTaskList";
$TotalNumberofSteps=3;
$TimeAllottedforEachStep="300"; //seconds

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------



//Clear the way for a new workflow


//How many workflows are open?
$result = $client->countOpenWorkflowExecutions([
    'domain' => $Domain_Name, 
    'startTimeFilter' => [
        'oldestDate' => 1524755000,
    ],
]);

$OpenWorkflowCount=$result["count"];


if ($OpenWorkflowCount <> 0){

//This loop terminates all the current workflows 
    for ($x = 1; $x <= $OpenWorkflowCount; $x++) {


$result = $client->listOpenWorkflowExecutions([
    'domain' => $Domain_Name, 
    'startTimeFilter' => [
        'oldestDate' => 1524755000,
    ],
]);

$OpenWorkflowID = $result["executionInfos"][0]["execution"]["workflowId"];
echo "You have an open workflow: $OpenWorkflowID.\n\n";
$WorkflowID=$OpenWorkflowID;
echo "Terminating Workflow $OpenWorkflowID...\n";
$Run_ID=$result["executionInfos"][0]["execution"]["runId"];
$Reason="Flow was terminated to clear the way for a new Workflow";
require 'TerminateFlow.php';

}

}



// Execution of the workflow begins now-----------------------------------------

// Generate a random workflow ID
$WorkflowID = mt_rand(1000, 9999);

//Turn it into a string for input to SWF
settype($WorkflowID,"string");


echo "\nRandomly Generated Workflow ID is ".$WorkflowID."\n";


//Let's get this party started.
$client->startWorkflowExecution([
    'domain' => $Domain_Name,
    'workflowId' => $WorkflowID,
    'workflowType' => [
        'name' => 'MainWorkflow',
        'version' => '1'
        ],
    'taskList' => [
        'name' => $Workflow_Task_List_Name
        ], 
    'input' => 'Starting a Workflow',
    //'executionStartToCloseTimeout' => '300',
   // 'taskStartToCloseTimeout' => '300',
   // 'childPolicy' => 'TERMINATE',
]);


echo "The workflow is now being executed!\n\n";
//echo "\nLet's ask the decider what to do next:\n";
require 'Decider.php';


//Here we will confirm completion of the workflow

 echo "Verifying Completion: \n";

$result = $client->describeWorkflowExecution([
    'domain' => $Domain_Name, 
    'execution' => [ 
        'runId' => $Run_ID,
        'workflowId' => $Workflow_ID,
    ],
]);


 $Finished = $result["executionInfo"]["closeStatus"];


 if ($Finished == 'COMPLETED')
 {
 echo "$Finished \nWe have completed the workflow!\n";
 }

 else {
  echo "$Finished \nCheck on your application.\n";
 }


 //This is the amount of time it took to run the workflow

  $WorkflowStartTimestamp=$result["executionInfo"]["startTimestamp"];
 $WorkflowEndTimestamp=$result["executionInfo"]["closeTimestamp"];
 $wfinterval = $WorkflowStartTimestamp->diff($WorkflowEndTimestamp);
    $m=$wfinterval->format('%i minute(s)');
    $s=$wfinterval->format('%s second(s)');

    echo "Running time: $m $s.\n\n";

?>

Decider.php:

<?php

//DECIDER




// What's on the agenda today boss?
$result = $client->pollForDecisionTask(array(
    "domain" => $Domain_Name,
    "taskList" => array(
        "name" => $Workflow_Task_List_Name
    ),
     "identity" => "Decider is choosing whether to continue or end the workflow",
    // "maximumPageSize" => 50,
    "reverseOrder" => true //This makes sure the events are returned in reverse order. It makes it easier to tell which event is current/most recent (helps generate $WorkflowEventID variable below).
));



// Parse info we need returned from the pollForDecisionTask call
$task_token = $result["taskToken"];
$Workflow_ID = $result["workflowExecution"]["workflowId"];
$Run_ID=$result["workflowExecution"]["runId"];
$WorkflowEventID = $result["events"][0]["eventId"];


// Our logic that decides what happens next...
//If we have x steps, we will need 3+x*6 WorkflowEventID's before sending the command to end the workflow.
//Here's where this is automatically calculated:
$CalculatedEventID=3+$TotalNumberofSteps*6;


//Below, we decide on whether to continue the workflow.
//It would be simpler to skip this section and only modify the section below, but 
//it allows us to avoid redundancy (for example, "require 'Worker.php';" below).

if($WorkflowEventID < $CalculatedEventID){
    $task_list = $Workflow_Task_List_Name;
    $continue_workflow = true;
}

elseif($WorkflowEventID == $CalculatedEventID){
    $task_list = $Workflow_Task_List_Name;
    $continue_workflow = false;
}





//------------------------------------------------------------------------------
//----------------------PROGRAMMER MODIFICATIONS--------------------------------
//------------------------------------------------------------------------------
// Now that we populated our variables based on what we received 
// from SWF, we need to tell SWF what we want to do next

// These loops assign variables the appropriate names/values for each Step based
//on the Event ID we're on. These variables are carried through to the worker.
//Variable values should be synonymous with the activity types in the SWF console.


if($continue_workflow === true){

 //Decider STEP 1---------------------------------------------------------------
    if ($WorkflowEventID == "3")

 {$Step = "Step 1";
     $Activity_Task_List_Name = "TaskList1";
     $Activity_ID = "1";
    // echo "The decider says its current Workflow ID is ".$Workflow_ID."\n\n";
 }


 //Decider STEP 2---------------------------------------------------------------  
    elseif ($WorkflowEventID == "9")

 {$Step = "Step 2";
    $Activity_ID = "2";
     $Activity_Task_List_Name = "TaskList2";
 }  

  //Decider STEP 3--------------------------------------------------------------
    elseif ($WorkflowEventID == "15")

 {$Step = "Step 3";
    $Activity_ID = "3";
     $Activity_Task_List_Name = "TaskList3";
 }  

else 
{echo "Something's Fishy\n\n";}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------




//We mark the Decision Task Complete before moving to the Worker

   $client->respondDecisionTaskCompleted(array(
        "taskToken" => $task_token,
        "decisions" => array(
            array(
                "decisionType" => "ScheduleActivityTask",
                "scheduleActivityTaskDecisionAttributes" => array(
                    "activityType" => array(
                        "name" => $Step,
                        "version" => $Activity_Type_Version
                    ),
                    "activityId" => $Activity_ID,
                    "control" => "Have a great day!",
                    // Customize timeout values
                    //"scheduleToCloseTimeout" => "360",
                    //"scheduleToStartTimeout" => "300",
                    "startToCloseTimeout" => $TimeAllottedforEachStep,
                    //"heartbeatTimeout" => "60",
                    "taskList" => array(
                        "name" => $Workflow_Task_List_Name
                    ),
                    "input" => "$Step Assigned to Worker"
                )
            )
        )
    ));


//Here we have the worker do the decider's bidding. 
     require 'Worker.php';




//The Timestamp stuff and response here can also be placed at the end of the worker script.
//They are placed here to simplify the worker script since the decider is 
//really supposed to be doing all the 'non-executing stuff' stuff. 


    $ReverseDescribeorNot=False;
    require 'DescribeExecution.php';

    $TimestampStart = $result["events"][$WorkflowEventID]["eventTimestamp"];
    $TimestampEnd   = $result["events"][$WorkflowEventID+4]["eventTimestamp"];
    $interval = $TimestampStart->diff($TimestampEnd);
    $m=$interval->format('%i minute(s)');
    $s=$interval->format('%s second(s)');


    echo $Step."/".$TotalNumberofSteps." completed in $m $s.\n\n";






 //We require the Decider here because if we do so in the Worker script, the worker script is unable to finish before being executed again above. 
 //This allows the Decider to loop back up to the top and figure out where it's at in the workflow and decide from there. 
 //Although it puts the Decider into a loop of itself, the if statements make sure it executes the correct things based on its feeback from SWF.
     require 'Decider.php';


}



// End workflow if last event ID was the final WorkflowEventID
else if($continue_workflow === false){
    $client->respondDecisionTaskCompleted(array(
        "taskToken" => $task_token,
        "decisions" => array(

            array(
                "decisionType" => "CompleteWorkflowExecution",

            ),
        )
    ));
}


?>

Worker.php:

<?php

//WORKER


//Typically, for SWF, a worker is a service, script, or person that performs a specific function. 
//For our purposes, all our workers are php scripts.
//Therefore, in order to avoid redundancy, we simply use this single script to activate our workers.
//Because developers don't want to worry about putting a "pollForActivityTask" and "respondActivityTaskCompleted" call in each of their scripts,
//we simply make those calls here and execute each script when SWF is ready for it. 


//echo "\nNow, the worker is working.\n\n";



// Check with SWF for activities
$result = $client->pollForActivityTask([
    "domain" => "Cloud Optimization",
    "taskList" => [
        "name" => $Workflow_Task_List_Name
    ]
]);


// Take out task token from the response above

$task_token = $result["taskToken"];




//------------------------------------------------------------------------------
//----------------------PROGRAMMER MODIFICATIONS--------------------------------
//------------------------------------------------------------------------------
// This is where the Worker actually executes activities

//Worker STEP 1-----------------------------------------------------------------
if ($Step == 'Step 1') {

require 'Test.php';

}

//Worker STEP 2-----------------------------------------------------------------
elseif ($Step == 'Step 2') {

require 'Test2.php';
}


//Worker STEP 3-----------------------------------------------------------------
elseif ($Step == 'Step 3') {
require 'Test3.php';
}

else 
{echo "Something's Super Duper Fishy\n\n";}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------



 //If the Activity Timed out, we'll find out here before our app explodes

 //This grabs the eventType statement associated with the current Workflow EventID

 $ReverseDescribeorNot=True;
 require 'DescribeExecution.php';
 $MightHaveTimedOut = $result["events"][1]["eventType"];



if ($MightHaveTimedOut == "ActivityTaskTimedOut")
{
    echo "\n$Step Timed Out, Cancelling Workflow...\n";
    $Reason="$Step Activity Timed Out";
    require 'TerminateFlow.php';
    exit;
}

else {

    $ResultResponse=$Step."/".$TotalNumberofSteps." completed.";
// Tell SWF that we finished what we need to do on this node
$client->respondActivityTaskCompleted(array(
    "taskToken" => $task_token,
    "result" => $ResultResponse
));


}


//echo "\nAaand now back to the decider.\n";


?>

TerminateFlow.php:

<?php

$result = $client->terminateWorkflowExecution([
    'childPolicy' => 'TERMINATE',
    'details' => $Reason,
    'domain' => $Domain_Name, // REQUIRED
    'reason' => $Reason,
    'runId' => $Run_ID,
    'workflowId' => $WorkflowID, // REQUIRED
]);

echo "Workflow $WorkflowID Terminated\n\n";

?>

描述執行:

<?php



// echo "\n\nExecution History:\n\n";

$result = $client->getWorkflowExecutionHistory([
    'domain' => $Domain_Name, 
    'execution' => [ 
        'runId' => $Run_ID,
        'workflowId' => $Workflow_ID,
    ],

//     'maximumPageSize' => <integer>,
//   'nextPageToken' => '<string>',
    'reverseOrder' => $ReverseDescribeorNot,//true || false,
]);


?>

Test.php:

<?php

echo "Test.php is executing!\n";

?>

Test2.php:

<?php

echo "Test2.php is executing!\n";

?>

Test3.php:

<?php

echo "Test3.php is executing!\n";

?>

終端輸出

只要腳本位於同一文件夾中,文件路徑就不應成為問題。 祝好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM