{"action":"created","issue":{"url":"https://api.github.com/repos/nsubstitute/NSubstitute/issues/264","repository_url":"https://api.github.com/repos/nsubstitute/NSubstitute","labels_url":"https://api.github.com/repos/nsubstitute/NSubstitute/issues/264/labels{/name}","comments_url":"https://api.github.com/repos/nsubstitute/NSubstitute/issues/264/comments","events_url":"https://api.github.com/repos/nsubstitute/NSubstitute/issues/264/events","html_url":"https://github.com/nsubstitute/NSubstitute/pull/264","id":191038073,"number":264,"title":"Track last call and specification in thread-safe manner","user":{"login":"Zvirja","id":1074182,"avatar_url":"https://avatars.githubusercontent.com/u/1074182?v=3","gravatar_id":"","url":"https://api.github.com/users/Zvirja","html_url":"https://github.com/Zvirja","followers_url":"https://api.github.com/users/Zvirja/followers","following_url":"https://api.github.com/users/Zvirja/following{/other_user}","gists_url":"https://api.github.com/users/Zvirja/gists{/gist_id}","starred_url":"https://api.github.com/users/Zvirja/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Zvirja/subscriptions","organizations_url":"https://api.github.com/users/Zvirja/orgs","repos_url":"https://api.github.com/users/Zvirja/repos","events_url":"https://api.github.com/users/Zvirja/events{/privacy}","received_events_url":"https://api.github.com/users/Zvirja/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":7,"created_at":"2016-11-22T15:28:47Z","updated_at":"2016-11-28T01:01:27Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/nsubstitute/NSubstitute/pulls/264","html_url":"https://github.com/nsubstitute/NSubstitute/pull/264","diff_url":"https://github.com/nsubstitute/NSubstitute/pull/264.diff","patch_url":"https://github.com/nsubstitute/NSubstitute/pull/264.patch"},"body":"Hi guys,\r\n\r\nThe intention from this PR was to better support concurrency in NSubsitute. Currently NSubstitute is very weak when you configure return values for call. If it happens that any invocation in background happens on same substitute, specification might become randomly broken.\r\nThis PR fixes all the tests in [this file](https://github.com/Zvirja/NSubstitute/blob/783f4716190fa7086204dab7167aa4ca8e54d284/Source/NSubstitute.Acceptance.Specs/ConcurrencyTests.cs) (except test with `async` - it didn't fail).\r\n\r\nI do understand that current weakness is likely \"by design\". However, concurrency is present everywhere in code and sometimes it isn't possible to avoid usage of substitute in background thread during the setup. That leads to very tricky issues that happen from time to time only.\r\nAlso I understand that it might be not possible to cover all the scenarios. But if something could be easily fixed - it's better to support that.\r\n\r\nChanges in PR:\r\n\r\n1. Use `ThreadLocal` for `IPendingSpecification`.\r\n2. Use `ILastCallTracker` to track last call in `RecordReplay` route using `ThreadLocal`.\r\n3. Use `ILastCallTracker` to get information about last call, rather than `ICallStack`.\r\n4. Rename `ICallStack` to `ICallCollection`. That is because the `Pop()` method is not required more (and was deleted), and `Delete()` method was added instead. That is much more collection that stack.\r\n\r\nP.S. Sorry for the large PR. I haven't found a way to split that to smaller set of changes - all them are related to each other."},"comment":{"url":"https://api.github.com/repos/nsubstitute/NSubstitute/issues/comments/263161735","html_url":"https://github.com/nsubstitute/NSubstitute/pull/264#issuecomment-263161735","issue_url":"https://api.github.com/repos/nsubstitute/NSubstitute/issues/264","id":263161735,"user":{"login":"dtchepak","id":70105,"avatar_url":"https://avatars.githubusercontent.com/u/70105?v=3","gravatar_id":"","url":"https://api.github.com/users/dtchepak","html_url":"https://github.com/dtchepak","followers_url":"https://api.github.com/users/dtchepak/followers","following_url":"https://api.github.com/users/dtchepak/following{/other_user}","gists_url":"https://api.github.com/users/dtchepak/gists{/gist_id}","starred_url":"https://api.github.com/users/dtchepak/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dtchepak/subscriptions","organizations_url":"https://api.github.com/users/dtchepak/orgs","repos_url":"https://api.github.com/users/dtchepak/repos","events_url":"https://api.github.com/users/dtchepak/events{/privacy}","received_events_url":"https://api.github.com/users/dtchepak/received_events","type":"User","site_admin":false},"created_at":"2016-11-28T01:01:27Z","updated_at":"2016-11-28T01:01:27Z","body":"Hi, sorry to comment and run last night (GMT+11).\r\nI'll spend more time on this as soon as I can, but so far can confirm the following:\r\n\r\n* doesn't happen with master\r\n* happens with the most recent checkins to this PR\r\n* happens in a huge, private test suite I have handy, haven't been able to find an isolated repro yet. Will take me a while to unpick this.\r\n* I haven't had a chance yet, but it is worth running [these long-running thread tests](https://github.com/nsubstitute/NSubstitute/blob/master/Source/NSubstitute.Acceptance.Specs/MultipleThreads.cs) over this PR to see if that shows any problems."}}
{"actor":{"display_login":"dtchepak"}}