We are current implementing a friend feature into our game, and given that the friends list feature of the Playfab API is pretty limited, we're using an approach where each player has a SharedGroup representing their "inbox" and when they send a friend request, we execute a cloud script that writes the request to the recipient's inbox and grants write access to the player's own inbox for future messaging. We also make some other calls in said script, such as grabbing some public data about the recipient (see below).
We're getting an odd error when running this script (through the web portal at the moment). It returns 200 OK but in the error log there is a 409 conflict code saying that we're making concurrent API calls on the same data. This is a bit confusing because a) it was my impression API calls in cloudscript were synchronous and b) as you can see from the script below the API call it's erroring on (and the two previous) are all involving different data objects (though I guess internally they could be in the same structure). Am I missing something here?
Also, if there is a better approach than what we're doing (which involves a good amount of API calls) please let me know.
handlers.sendFriendRequest = function (args) // args: playerId, friendId, playerTags
{
// Get friend's inbox (server call #1)
var friendInboxId = "inbox." + args.friendId;
var friendInbox = server.GetSharedGroupData({ "SharedGroupId": friendInboxId, "Keys": [ args.playerId ] });
// If they have too many keys, reject request
if(Object.keys(friendInbox.Data).length >= 100) {
return { success: false, inboxFull: true };
}
else {
// Get info about friend (server call #2)
var friendPublicData = server.GetUserData({ "PlayfabId": args.playerId });
var friendTags = [];
for(var key in friendPublicData.Data) {
var dataItem = friendPublicData.Data[key];
if(dataItem.Permission == "Public") {
friendTags.push(key + "=" + dataItem.Value);
}
}
// **** 409 Conflict on the API call below*******
// Add write access for friend to player's inbox (server call #3)
var inboxId = "inbox." + args.playerId;
server.AddSharedGroupMembers({ "SharedGroupId": inboxId, "PlayfabIds": [ args.friendId ] });
// Write your inbox with request to friend (server call #4)
var playerInbox = {};
playerInbox[args.friendId] = JSON.stringify({ state: "youRequested" });
server.UpdateSharedGroupData({ "SharedGroupId": inboxId, "Data": playerInbox });
// Write friends' inbox with request from player and also tags (server call #5)
friendInbox.Data[args.playerId] = JSON.stringify({ state: "theyRequested", tags: args.playerTags });
server.UpdateSharedGroupData({ "SharedGroupId": friendInboxId, "Data": friendInbox.Data });
// Send push notif to friend (server call #5)
// TODO: Localize?
server.SendPushNotification({ Recipient: args.friendId, Subject: "Friend Request", Message: "Someone sent you a friend request!" });
//
// Client needs to add friend and add tags
//
return { success: true, tags: friendTags };
}
};
{
"code": 200,
"status": "OK",
"data": {
"FunctionName": "sendFriendRequest",
"Revision": 4,
"Logs": [
{
"Level": "Error",
"Message": "PlayFab API request error",
"Data": {
"api": "/Server/AddSharedGroupMembers",
"request": {
"SharedGroupId": "inbox.8C5EAAAF8D9E7496",
"PlayfabIds": [
"697CCCAE25C857DA"
]
},
"result": null,
"apiError": {
"code": 409,
"status": "Conflict",
"error": "A conflict occurred trying to make multiple edits to the same data at the same time. This often indicates that there are multiple concurrent requests to the same API for the same player",
"errorCode": 1133,
"errorMessage": "A conflict occurred trying to make multiple edits to the same data at the same time. This often indicates that there are multiple concurrent requests to the same API for the same player",
"errorHash": "65ba5f215fed75a685df08ad8df2c088",
"errorDetails": {
"RequestID": [
"4cba8cc90b064162a8948552e55ee164"
]
}
}
}
}
],
"ExecutionTimeSeconds": 0.1202221,
"MemoryConsumedBytes": 83696,
"APIRequestsIssued": 3,
"HttpRequestsIssued": 0,
"Error": {
"Error": "CloudScriptAPIRequestError",
"Message": "The script called a PlayFab API, which returned an error. See the Error logs for details.",
"StackTrace": "Error\n at handlers.sendFriendRequest (4F78-main.js:37:12)"
}
},
"CallBackTimeMS": 398
}