如何传递和处理参数 Durable Functions v4 javascript?

问题描述 投票:0回答:1

我对 javascript 中的持久函数 V4 很陌生,但我无法让此活动正常运行。我总是收到错误,因为显然我没有正确传递实例 ID。

我在这里做错了什么?微软网站上的教程页面没有用。

这是代码:

df.app.orchestration('reportOrchestrator', function* (context) {
   try {
       const instanceId = context.df.instanceId; // Get the current orchestration's instance ID
       context.log(`Orchestration instance ID: ${instanceId}`);

       const lsFile = { instanceID: instanceId }; // Pass instanceID in an object
       const token = yield context.df.callActivity('TokenManager', { instanceID: instanceId }); 

context.log(`Token retrieved: ${token}`);


return token;

  // const result = yield context.df.callActivity('PipelineQuery', { token });

  } catch (error) {
    return error.message;
    context.log(`Error in orchestration: ${error.message}`);
    throw error;
  }
});
df.app.activity('TokenManager', {
   handler: async (context) => {
        const log = context.log;

         const lsFile = context.getClient().instanceID; // Direct input passed from the orchestrator

if (!lsFile || !lsFile.instanceID) {
    //log("InstanceID is missing or undefined");
    throw new Error("InstanceID is missing or undefined,", context);
}

const instanceID = lsFile;
//log(`Orchestrator Instance ID is ${instanceID}`);

let functionID = "POST Reports Orchestrator";

try {
    // Make the POST request to retrieve the token
    const tokenResponse = await axios.post(logicAppURL, {
        requestType: "GET_TOKEN",
        functionID: functionID,
    });

    // Check if token was successfully retrieved
    if (tokenResponse.data && tokenResponse.data.token) {
        //log("Token successfully retrieved");
        return tokenResponse.data.token;
    } else {
        //log("Token could not be retrieved. Functions will generate their own token");
        await mandrillGeneralError(log, "Error retrieving token on POST Reports Orchestrator Token Manager function app in Azure.");
        return ""; // Return empty token if retrieval fails
    }

} catch (error) {
    //log(`Error retrieving token: ${error.message}`);
    await mandrillGeneralError(log, `Error retrieving token: ${error.message}`);
    throw error; // Throw the error so it's logged properly by Durable Functions
}
}
  });
javascript azure-durable-functions
1个回答
0
投票

我尝试了你的代码并得到了同样的错误:

incorrect Instance ID

发生这种情况是因为

instance ID
每次运行时都会发生变化。
instance ID
是实例的唯一标识符,如果您不指定此参数,该方法将使用随机 ID。

我已参考此文档了解 JavaScript 中的持久函数

下面的代码用于检索持久函数中的令牌,并通过此 git 链接获取完整代码。

const axios = require('axios');

async function generateToken(logicAppURL, instanceID) {
    if (!instanceID) {
        throw new Error("InstanceID is missing or undefined.");
    }

    console.log(`Orchestrator Instance ID is ${instanceID}`);

    try {
        const tokenResponse = await axios.post(logicAppURL, {
            // requestType: "GET_TOKEN", // Uncomment and customize if needed
            // functionID: functionID,   // Uncomment and customize if needed
        });

        if (tokenResponse.data && tokenResponse.data.token) {
            console.log("Token successfully retrieved");
            return tokenResponse.data.token;
        } else {
            console.log("Token could not be retrieved. Returning an empty token.");
            return "";  
        }

    } catch (error) {
        console.error(`Error retrieving token: ${error.message}`);
        throw error;  
    }
}
const logicAppURL = "<Your Logic App URL>";
const instanceID = "your-instance-id";
generateToken(logicAppURL, instanceID)
    .then(token => console.log(`Generated Token: ${token}`))
    .catch(error => console.error(error));




输出:

enter image description here

enter image description here

我参考了这个git来传递和处理参数持久函数。

在您的代码中,我看到

logicAppURL
(或)
anyURl
使用
post /get
请求,将实例 ID 传递给名为
TokenManager
FunctionId
的活动函数。

一般来说,如果实例 ID 每次都更改,则不要使用实例 ID 作为参数,并且

FunctionId
属性为 Azure Function 提供唯一标识符,该标识符由主机分配。

module.exports = async function (context, req) {
    const functionId = context.executionContext.functionName;
    context.log(`Function ID: ${functionId}`);



此标识符在同一函数的多次调用中保持稳定,从而实现一致的跟踪和记录。

有关实例 ID 和函数 ID 的更多详细信息,请参阅此 Msdoc1Msdoc2

    const invocationId = context.executionContext.invocationId;

    context.log(`Invocation ID: ${invocationId}`);

另外,参考这个SO获取逻辑应用的标识符,并在传入post请求时检查上面的字段。

另一种方法是仅使用logicAppURL请求中的url进行post/get请求,而不使用functionID、Instance ID。

我已参考链接从逻辑应用程序获取令牌。


const axios = require('axios');
const { app } = require('@azure/functions');
const df = require('durable-functions');

const tenantId = 'tenantId'; 
const clientId = 'clientId';
const clientSecret = 'clientSecret'; 

async function getAccessToken() {
    const url = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
    
    const params = new URLSearchParams();
    params.append('grant_type', 'client_credentials');
    params.append('client_id', clientId);
    params.append('client_secret', clientSecret);
    params.append('scope', 'https://management.azure.com/.default');

    try {
        const response = await axios.post(url, params, {
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            }
        });
        const accessToken = response.data.access_token;
        console.log('Access Token:', accessToken);
        return accessToken; 
    } catch (error) {
        console.error('Error retrieving access token:', error.response ? error.response.data : error.message);
    }
}

const activityName = 'durableHello1';

df.app.orchestration('durableHello1Orchestrator', function* (context) {
    const input = context.df.getInput();
    const outputs = [];
    const accessToken = yield context.df.callActivity('getAccessTokenActivity', null);
    
    for (const city of input.cities || ['Tokyo']) {
        outputs.push(yield context.df.callActivity(activityName, city));
    }

    return { greetings: outputs, accessToken };
});

df.app.activity(activityName, {
    handler: (input) => {
        return `Hello, ${input}`;
    },
});
df.app.activity('getAccessTokenActivity', {
    handler: async () => {
        return await getAccessToken();
    },
});

app.http('durableHello1HttpStart', {
    route: 'orchestrators/{orchestratorName}',
    extraInputs: [df.input.durableClient()],
    handler: async (request, context) => {
        const client = df.getClient(context);
        const body = await request.json();
        const instanceId = await client.startNew(request.params.orchestratorName, undefined, body);
        context.log(`Started orchestration with ID = '${instanceId}'.`);
        return client.createCheckStatusResponse(request, instanceId);
    },
});


enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.