This call to t.set is made after receiving a response from our API. It is the only call made to set shared data. The other response from pluginData in the screenshot above is a successful t.set('member', 'private') call.
Writing shared board data is the only thing that seems to be affected. The shared values persist in memory, but upon refresh they are gone. I am guessing because of the 409 received prior.
Oddly enough, I can get the shared values to stick when calling in response to a button click in the power up. When I make them in response to a successful post request to our API it seems to fail.
t.set() is a wrapper around a ‘upsert’ function which makes an API call to the pluginData endpoint, with either a POST if there is no data already in the database, or a PUT if there is already data. I believe the issue is that we are sending POST requests even though we should be sending PUT requests, thus resulting in the unexpected 409.
can you explain more of the context of t.set() call? once we know more about how that function is called, we can try to dig in to the data conflict.
This function is called after the initial setup of our power-up and in response to a user interaction. We are effectively trying to set a shared value inside this process:
function autoSyncBoard(companyId) {
t.board('id', 'name')
.then(board =>
createProjectForBoard(companyId, board)
.then(project => {
trackSegmentEvent('trello_sync_set', {
method: 'auto',
});
// ATTEMPTING TO USE t.set('board', 'shared', 'key', 'value') HERE
t.set('board', 'shared', 'my-key', 'my-value'); // this always fails with the conflict
return syncProjectToBoard(t, project.id);
})
.then(() => syncDateOverlay(t))
)
.catch(error => {
autoSyncWarning.text(error.message);
});
}
could you please describe the user interaction that is triggering this call? i’m working on trying to reproduce your error and this information would be helpful. i am not able to reproduce this error using a board button.
There doesn’t seem to be any noticeable reason why this should be failing, and I don’t think I can give an exhaustive treatment of everything that transpires, but writing a shared value inside this whole processes ALWAYS fails.
okay, i think i understand the usage of this function in your code. thanks for your clarification.
when i made a call t.set('board', 'shared', 'my-key', 'my-value'), the request payload has value: "{\"my-key\":\"my-value\"}". however, in the screenshot you shared, the value has two key value pairs, indicating that there already was pluginData on the shared board level. the client should have run a PUT request instead of a POST, though i’m having some difficulty in figuring out why the wrong method was used.
i wonder if there might be some sort of corrupted data or schema that is messing up the web client logic. could you share the results of going to https://trello.com/1/boards/<shortUrl>/plugindata? feel free to anonymize any data as you see fit.
otherwise, here’s some other questions that would provide more information:
have you tested this situation on a fresh board, i.e. on a board that has not had this plugin enabled? what are the results if you try it?
have you enabled/disabled this plugin on the board recently?
is the correct data returned when you run ‘t.get’ on your specific key? can you run ‘t.remove’?
thanks for your patience as i work on this. i can’t reproduce this error locally, so i’m having to rely on your information to try to debug it.
I tested this on a fresh board, and it works as expected (initially)*
Part of our local development process involves enabling/disabling frequently on a single board
Correct data is returned on the fresh board
The plugindata url shows the correct data on the fresh board, but the shared data is never returned on the existing board.
The fresh board only works the first time I set shared data. All subsequent attempts (after disabling/enabling the power up again) return me to the 409 state:
The first time I enable the power up on a fresh board, helloWorld is set correctly. Subsequent disabling followed by enabling causes the 409 to return.
hmm, okay. does the function createProjectForBoard modify board shared data? how are you using the board parameter in this function?
i ask because, if you’ve only set the hellowWorld key in the call as you’ve indicated, it should be the only value in the pluginData when you fetch that data on a fresh board. since there are multiple key/value pairs, i’m guessing the createProjectForBoard function also creates shared board data. is that guess correct?
The syncProjectToBoard function also sets shared data. A modal via t.modal is spawned by syncDateOverlay(t) That modal has a button that sets shared data as well.
The respective functions are:
// projectId is a number type
export function setSyncedProjectId(t, projectId) {
return t.set('board', 'shared', SYNC_PROJECT_ID_KEY, projectId);
}
// syncDates is a boolean
export function updateSyncDates(t, syncDates) {
return t.set('board', 'shared', SYNC_DATES_KEY, syncDates);
}
If it is helpful, we did try grouping these all into a single t.set to see if it helped, but it did not appear to make a difference.
@BrianScaturro Weird question but I have to rule something out:
When you’re testing all of this, are the plugin, board, and member you are logged in as all part of the same workspace? There is a very obscure bug right now where the plugin data websocket can be disconnected if you are on a board with a private plugin, but you are not a part of that workspace that owns the board and the private plugin.
@BrianScaturro Also you say you are enabling and disabling the Power-Up in between the t.set() calls. Why are you doing that, and do you have any on-enable or on-disable capabilities?
The enabling/disabling is because the feature in question is part of the enable flow. When a user enables the power-up, we collect some info to setup the environment for synchronizing with our service.
If we have on-disable capabilities are present, is it idiomatic to remove shared data as part of that process?
And to give you a bit of insight about what’s going on with this bug:
The first time you set a shared plugin data on a board (i.e. call t.set('board', 'shared') for the first time on a board), the web client will POST to /pluginData. This creates a new pluginData object for this board with the shared access. You can view the new object by going to the /pluginData route.
Afterwards, attempting to set more shared board plugindata will send a PUT instead, to update the existing pluginData object.
This 409:Conflict error happens because the web client mistakenly tries to POST to pluginData when that pluginData object already exists. It should be doing a PUT to the existing data instead.
We’re currently trying to investigate why this error occurs and if it’s a widespread issue. Thanks for working with us!
hi everyone, we did a bunch of digging on this and it seems that our websockets weren’t configured correctly, so the model that was modified was not receiving updates for pluginData changes. we’ve rolled out a change to our websockets platform that should fix this, and our logs seem to indicate a decrease in this error. please let us know if there are any new problems, and thanks for working with us!
sorry to hear that! i was really hoping that our websockets fix would catch this. :\
let’s try looking at your websockets. you can see the trello websocket in the developer console, under network > WS. can you please send me a screenshot of the request and response headers? you might have to block out a cookie or other sensitive data.
otherwise, you can check your websocket activity (under network > WS > client websocket > messages) as you try setting data. if you aren’t seeing an ‘updateModel’ message when you change power-up data, we know it’s the websockets not sending information correctly.
We believe we’ve pinpointed the issue. There was a bug that was introduced in a security fix we did relating to plugin data from a while back. We’re working on a fix and will keep you updated. Thank you so much for working with us so far!