question

The Tap Lab avatar image
The Tap Lab asked

Cloudscript and 409 Conflict

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
}
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

1 Answer

·
brendan avatar image
brendan answered

Reviewing the logs, that error actually appears to be caused by trying to add a user to a Shared Group Data via AddSharedGroupMembers, when that PlayFab ID has already been added to the Shared Group Data in question. I'll get a bug filed to get a better error message for that, but I would strongly recommend not using AddSharedGroupMembers at all. That's only intended for scenarios where you fully trust the client, or don't care what the client does with the data, as a hacked client could write anything it wanted to in the Shared Group Data, once added. Instead, just use well-formed IDs for the Shared Group Data (as in your example), and have the Cloud Script code make all the modifications.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.