mattermost-plugin-github icon indicating copy to clipboard operation
mattermost-plugin-github copied to clipboard

Make access to KV store atomically safe when saving/removing subscriptions

Open mickmister opened this issue 5 years ago • 11 comments

Summary

For subscriptions of GitHub projects to MM channels, all of the subscription configuration is stored in the subscriptions portion of the KV store slice that is used by the Github plugin. In order to avoid race conditions and conflicts when two users are concurrently editing subscriptions, we should wrap the operations in a function like atomicModify used in the Jira plugin.

Ticket Link

https://mattermost.atlassian.net/browse/MM-18722


If you're interested please comment here and come join our "Contributors" community channel on our daily build server, where you can discuss questions with community members and the Mattermost core team. For technical advice or questions, please join our "Plugin: GitHub" community channel.

New contributors please see our Developer's Guide and our Plugins Guide.

mickmister avatar Oct 14 '19 16:10 mickmister

I'll take this one.

gsagula avatar Oct 17 '19 17:10 gsagula

@mickmister @hanzei Quick update: This issue is part of my tryout but I won't be able to start working on it until Oct 28.

cc: @jwilander

gsagula avatar Oct 19 '19 02:10 gsagula

Thanks for the heads up @gsagula. Looking forward to you working on this :+1:

hanzei avatar Oct 19 '19 12:10 hanzei

@mickmister @hanzei Quick question before I start working on this issue. If I understand it correctly, atomicModify function should only attempt to modify the subscriptions when the key exists in the KV storage and the initial value is equal to the current value. I'm not sure why true is being passed to success here:

success := false
for !success {
	initialBytes, newValue, err := readModify()
	if err != nil {
		return err
	}

	var setError *model.AppError
	success, setError = p.API.KVCompareAndSet(key, initialBytes, newValue)
	success = true
	if setError != nil {
		return errors.Wrap(setError, "problem writing value")
	}
}

Should this loop continue when p.API.KVCompareAndSet(key, initialBytes, newValue) returns false, nil, so that readModify can fetch new initial bytes and KVCompareAndSet can attempt to set the modified bytes again?

gsagula avatar Oct 29 '19 07:10 gsagula

Hi @gsagula,

It seems that the success = true line may be a bug. This line was introduced before the switch to using api.KVCompareAndSet, which gives us a success return value, but the success = true line was kept as well, (before and after). It makes sense to me to use the success value returned from KVCompareAndSet instead of the hardcode below the call. @crspeller do you know if leaving the success = true line was intentional after the switch?

Also, there was discussion about making the function into a helper (including a retry limit), so multiple plugins can reuse the same code: https://github.com/mattermost/mattermost-plugin-jira/pull/61/files#r286163455 . This is probably a good route to take for this ticket. What are your thoughts @gsagula?

mickmister avatar Oct 29 '19 21:10 mickmister

Thanks @mickmister,

I agree with limiting retries. Anything that allows controlling bursts so we can minimize chances of resource starvation. Something like a token bucket should probably be enough. WDYT?

I'm still getting familiar with the design. Is helpers_kv.go a good place to implement the helper?

gsagula avatar Oct 30 '19 04:10 gsagula

Something like a token bucket should probably be enough. WDYT?

Looks like a great solution, looking forward to the implementation!

I'm still getting familiar with the design. Is helpers_kv.go a good place to implement the helper?

Yep :+1:

mickmister avatar Oct 30 '19 04:10 mickmister

@mickmister Ya that looks like a bug.

crspeller avatar Oct 30 '19 16:10 crspeller

@gsagula do we still need this ticket, or has it been (indirectly?) resolved?

levb avatar Dec 10 '19 13:12 levb

I need to finish https://github.com/mattermost/mattermost-server/pull/13002 before getting back to this one.

gsagula avatar Dec 11 '19 15:12 gsagula

https://github.com/mattermost/mattermost-server/pull/13805 has to be done first

hanzei avatar Mar 07 '20 15:03 hanzei