{"action":"created","issue":{"url":"https://api.github.com/repos/apache/spark/issues/20997","repository_url":"https://api.github.com/repos/apache/spark","labels_url":"https://api.github.com/repos/apache/spark/issues/20997/labels{/name}","comments_url":"https://api.github.com/repos/apache/spark/issues/20997/comments","events_url":"https://api.github.com/repos/apache/spark/issues/20997/events","html_url":"https://github.com/apache/spark/pull/20997","id":311974969,"number":20997,"title":"[SPARK-19185] [DSTREAMS] Avoid concurrent use of cached consumers in CachedKafkaConsumer","user":{"login":"gaborgsomogyi","id":18561820,"avatar_url":"https://avatars2.githubusercontent.com/u/18561820?v=4","gravatar_id":"","url":"https://api.github.com/users/gaborgsomogyi","html_url":"https://github.com/gaborgsomogyi","followers_url":"https://api.github.com/users/gaborgsomogyi/followers","following_url":"https://api.github.com/users/gaborgsomogyi/following{/other_user}","gists_url":"https://api.github.com/users/gaborgsomogyi/gists{/gist_id}","starred_url":"https://api.github.com/users/gaborgsomogyi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gaborgsomogyi/subscriptions","organizations_url":"https://api.github.com/users/gaborgsomogyi/orgs","repos_url":"https://api.github.com/users/gaborgsomogyi/repos","events_url":"https://api.github.com/users/gaborgsomogyi/events{/privacy}","received_events_url":"https://api.github.com/users/gaborgsomogyi/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":18,"created_at":"2018-04-06T13:26:02Z","updated_at":"2018-05-22T20:42:44Z","closed_at":null,"author_association":"CONTRIBUTOR","pull_request":{"url":"https://api.github.com/repos/apache/spark/pulls/20997","html_url":"https://github.com/apache/spark/pull/20997","diff_url":"https://github.com/apache/spark/pull/20997.diff","patch_url":"https://github.com/apache/spark/pull/20997.patch"},"body":"## What changes were proposed in this pull request?\r\n\r\n`CachedKafkaConsumer` in the project streaming-kafka-0-10 is designed to maintain a pool of KafkaConsumers that can be reused. However, it was built with the assumption there will be only one thread trying to read the same Kafka TopicPartition at the same time. This assumption is not true all the time and this can inadvertently lead to ConcurrentModificationException.\r\n\r\nHere is a better way to design this. The consumer pool should be smart enough to avoid concurrent use of a cached consumer. If there is another request for the same TopicPartition as a currently in-use consumer, the pool should automatically return a fresh consumer.\r\n\r\n- There are effectively two kinds of consumer that may be generated\r\n  - Cached consumer - this should be returned to the pool at task end\r\n  - Non-cached consumer - this should be closed at task end\r\n- A trait called `KafkaDataConsumer` is introduced to hide this difference from the users of the consumer so that the client code does not have to reason about whether to stop and release. They simply call `val consumer = KafkaDataConsumer.acquire` and then `consumer.release`.\r\n- If there is request for a consumer that is in-use, then a new consumer is generated.\r\n- If there is request for a consumer which is a task reattempt, then already existing cached consumer will be invalidated and a new consumer is generated. This could fix potential issues if the source of the reattempt is a malfunctioning consumer.\r\n- In addition, I renamed the `CachedKafkaConsumer` class to `KafkaDataConsumer` because is a misnomer given that what it returns may or may not be cached.\r\n\r\n## How was this patch tested?\r\n\r\nA new stress test that verifies it is safe to concurrently get consumers for the same TopicPartition from the consumer pool.\r\n"},"comment":{"url":"https://api.github.com/repos/apache/spark/issues/comments/391133870","html_url":"https://github.com/apache/spark/pull/20997#issuecomment-391133870","issue_url":"https://api.github.com/repos/apache/spark/issues/20997","id":391133870,"user":{"login":"vanzin","id":1694083,"avatar_url":"https://avatars0.githubusercontent.com/u/1694083?v=4","gravatar_id":"","url":"https://api.github.com/users/vanzin","html_url":"https://github.com/vanzin","followers_url":"https://api.github.com/users/vanzin/followers","following_url":"https://api.github.com/users/vanzin/following{/other_user}","gists_url":"https://api.github.com/users/vanzin/gists{/gist_id}","starred_url":"https://api.github.com/users/vanzin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vanzin/subscriptions","organizations_url":"https://api.github.com/users/vanzin/orgs","repos_url":"https://api.github.com/users/vanzin/repos","events_url":"https://api.github.com/users/vanzin/events{/privacy}","received_events_url":"https://api.github.com/users/vanzin/received_events","type":"User","site_admin":false},"created_at":"2018-05-22T20:42:44Z","updated_at":"2018-05-22T20:42:44Z","author_association":"CONTRIBUTOR","body":"That being the case, merging to master."}}
{"actor":{"display_login":"vanzin"}}