{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/orleans/issues/61","labels_url":"https://api.github.com/repos/dotnet/orleans/issues/61/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/orleans/issues/61/comments","events_url":"https://api.github.com/repos/dotnet/orleans/issues/61/events","html_url":"https://github.com/dotnet/orleans/issues/61","id":56129800,"number":61,"title":"Managing state when refactoring grains?","user":{"login":"BenjaminGibbs","id":7413070,"avatar_url":"https://avatars.githubusercontent.com/u/7413070?v=3","gravatar_id":"","url":"https://api.github.com/users/BenjaminGibbs","html_url":"https://github.com/BenjaminGibbs","followers_url":"https://api.github.com/users/BenjaminGibbs/followers","following_url":"https://api.github.com/users/BenjaminGibbs/following{/other_user}","gists_url":"https://api.github.com/users/BenjaminGibbs/gists{/gist_id}","starred_url":"https://api.github.com/users/BenjaminGibbs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BenjaminGibbs/subscriptions","organizations_url":"https://api.github.com/users/BenjaminGibbs/orgs","repos_url":"https://api.github.com/users/BenjaminGibbs/repos","events_url":"https://api.github.com/users/BenjaminGibbs/events{/privacy}","received_events_url":"https://api.github.com/users/BenjaminGibbs/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dotnet/orleans/labels/question","name":"question","color":"cc317c"}],"state":"open","locked":false,"assignee":{"login":"jthelin-microsoft","id":10134641,"avatar_url":"https://avatars.githubusercontent.com/u/10134641?v=3","gravatar_id":"","url":"https://api.github.com/users/jthelin-microsoft","html_url":"https://github.com/jthelin-microsoft","followers_url":"https://api.github.com/users/jthelin-microsoft/followers","following_url":"https://api.github.com/users/jthelin-microsoft/following{/other_user}","gists_url":"https://api.github.com/users/jthelin-microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/jthelin-microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jthelin-microsoft/subscriptions","organizations_url":"https://api.github.com/users/jthelin-microsoft/orgs","repos_url":"https://api.github.com/users/jthelin-microsoft/repos","events_url":"https://api.github.com/users/jthelin-microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/jthelin-microsoft/received_events","type":"User","site_admin":false},"milestone":null,"comments":10,"created_at":"2015-01-31T16:18:35Z","updated_at":"2015-02-02T18:01:24Z","closed_at":null,"body":"As projects move forward requirements change and code ends up being refactored, this could as simple as a namespace being changed, or Oect1Grain being renamed to Object2Gain etc..\r\n\r\nWhat is the recommend way of handling state when this happens? as my understanding from looking at how the state is stored, the grain type is linked to the state record (for example in Azure Storage it becomes the RowKey). Which would imply that refactoring/renaming the grain or namespace would break the reading of the previous state when the service is updated.\r\n\r\nOne possible solution could to be to add an attribute to the grain (like we do with the storage provider) which allows us to specify the Type as string to override the default type that would be provided enabling backwards compatibility with old state? \r\n\r\nI'd would be interested to hear how others are approaching the scenario, or point out something I may have missed.\r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/orleans/issues/comments/72504703","html_url":"https://github.com/dotnet/orleans/issues/61#issuecomment-72504703","issue_url":"https://api.github.com/repos/dotnet/orleans/issues/61","id":72504703,"user":{"login":"gabikliot","id":10171207,"avatar_url":"https://avatars.githubusercontent.com/u/10171207?v=3","gravatar_id":"","url":"https://api.github.com/users/gabikliot","html_url":"https://github.com/gabikliot","followers_url":"https://api.github.com/users/gabikliot/followers","following_url":"https://api.github.com/users/gabikliot/following{/other_user}","gists_url":"https://api.github.com/users/gabikliot/gists{/gist_id}","starred_url":"https://api.github.com/users/gabikliot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gabikliot/subscriptions","organizations_url":"https://api.github.com/users/gabikliot/orgs","repos_url":"https://api.github.com/users/gabikliot/repos","events_url":"https://api.github.com/users/gabikliot/events{/privacy}","received_events_url":"https://api.github.com/users/gabikliot/received_events","type":"User","site_admin":false},"created_at":"2015-02-02T18:01:24Z","updated_at":"2015-02-02T18:01:24Z","body":"I like how @sergeybykov ordered the options. From the more automatically managed by Orleans to the least managed.\r\nThere is also potentially a fourth option (zero option in this ordering), even more managed by Orleans.\r\nIt will be like now and in addition we checkpoint (do WriteASync) after every operation. That way the app code does not need to explicitly checkpoint at all. In fact, we went back and forth a lot between that option and what we finally picked (app does explicit checkpoints).\r\nIn that new option we could also make it even more managed, for example by automatically rolling back the state in case of failures. There are a lot of possibilities here.\r\n\r\nAnd it totally fine I think that one option does not cover all cases."}}