Skip to content

Fix schema not added when subscribe an empty topic without schema - #9853

Merged
codelipenghui merged 5 commits into
apache:masterfrom
BewareMyPower:bewaremypower/fix-consumer-schema
Mar 11, 2021
Merged

Fix schema not added when subscribe an empty topic without schema#9853
codelipenghui merged 5 commits into
apache:masterfrom
BewareMyPower:bewaremypower/fix-consumer-schema

Conversation

@BewareMyPower

@BewareMyPower BewareMyPower commented Mar 9, 2021

Copy link
Copy Markdown
Contributor

Fixes #7728

Motivation

When a consumer with a schema subscribes an empty topic without schema, the current check uses isActive, which only checks if the topic can be deleted. However, it should check if there's any connected producer or consumer of this topic. For current implementation, even if a topic has no active producers of consumers, the topic's subscription list may be not empty and isActive will return true. Then the schema of consumer won't be attached to the topic and it will throw an IncompatibleSchemaException.

Modifications

  • Check if the topic has active producers or consumers instead of whether it can be deleted.
  • Add related tests.

Verifying this change

  • Make sure that the change passes the CI checks.

(Please pick either of the following options)

This change added tests testAutoCreatedSchema.

@BewareMyPower

BewareMyPower commented Mar 9, 2021

Copy link
Copy Markdown
Contributor Author

Update: this PR is compatible with #2669 now.


I think this change may need a discussion since it's not compatible with #2669.

@ivankelly @congbobo184 @codelipenghui

@BewareMyPower

Copy link
Copy Markdown
Contributor Author

/pulsarbot run-failure-checks

@codelipenghui

Copy link
Copy Markdown
Contributor

@BewareMyPower I think the root cause is the producer has written data into the topic but the schema does not upload? From the perspective of schema compatibility, if the topic has data but does not have a schema, this means the schema is bytes schema(Currently bytes schema is not uploaded), so I think the right fix is to trade as The topic with bytes schema, we should check the schema compatibility of the new producers/consumers.

Currently, the producer side also has a problem is a producer produce some message with bytes schema, then a new producer can publish messages with other schemas(e.g. Schema.INT64), this will introduce schema compatibility issues. Imagine that if a consumer consumes messages from the earliest position with Schema.INT64, will pass the schema compatibility check but will fail when deserializing messages.

@BewareMyPower

BewareMyPower commented Mar 9, 2021

Copy link
Copy Markdown
Contributor Author

@codelipenghui

if the topic has data but does not have a schema

I agree, so even if hasSchema is false, if ledger.getTotalSize() != 0, we should still go to checkSchemaCompatibleForConsumer.

However, I don't understand why we also need the check of isActive(InactiveTopicDeleteMode.delete_when_no_subscriptions). It causes the failure of testAutoCreatedSchema before applying changes of this PR since the topic has no data and it shouldn't fail. Does changing the conditional check to if (hasSchema || (ledger.getTotalSize() != 0)) have any problem?

@codelipenghui

Copy link
Copy Markdown
Contributor

Does changing the conditional check to if (hasSchema || (ledger.getTotalSize() != 0)) have any problem?

We need to check if there are producers or consumers connect to this topic. Otherwise, if the old producers and consumers connect with bytes schema, then we change the schema type to schema.AVRO, this will break the old producers and consumers.

Check no subscriptions is equals to no consumers.

@BewareMyPower BewareMyPower changed the title Fix schema not added when subscribe a topic without schema [WIP] Fix schema not added when subscribe a topic without schema Mar 10, 2021
@BewareMyPower

Copy link
Copy Markdown
Contributor Author

We need to check if there are producers or consumers connect to this topic.

Check no subscriptions is equals to no consumers.

So even the consumer has closed, it's still treated as connected? Take my test as the example

        try (Consumer<byte[]> consumer
                     = pulsarClient.newConsumer(Schema.BYTES).topic(topic2).subscriptionName("sub").subscribe()) {
        }
        try (Consumer<String> consumer
                     = pulsarClient.newConsumer(Schema.STRING).topic(topic2).subscriptionName("sub").subscribe()) {
        }

During the ServerCnx#handleSubscribe for the second consumer, the subscriptions is not empty. However the first consumer has already closed.

@codelipenghui

Copy link
Copy Markdown
Contributor

If all consumers disconnected from a subscription, I think the subscription will remove from the topic? If not, we should check consumer size, This will be more clear.

@BewareMyPower BewareMyPower changed the title [WIP] Fix schema not added when subscribe a topic without schema [WIP] Fix schema not added when subscribe an empty topic without schema Mar 10, 2021
@BewareMyPower BewareMyPower changed the title [WIP] Fix schema not added when subscribe an empty topic without schema Fix schema not added when subscribe an empty topic without schema Mar 10, 2021
@BewareMyPower BewareMyPower changed the title Fix schema not added when subscribe an empty topic without schema [WIP] Fix schema not added when subscribe an empty topic without schema Mar 10, 2021
@BewareMyPower

BewareMyPower commented Mar 10, 2021

Copy link
Copy Markdown
Contributor Author

update: The integration test is just a flaky test.


There's still a test failure in testPrimitiveSchemaTypeCompatibilityCheck, and the number of producers should also be checked here. I'll fix it soon.

@BewareMyPower BewareMyPower changed the title [WIP] Fix schema not added when subscribe an empty topic without schema Fix schema not added when subscribe an empty topic without schema Mar 10, 2021
@BewareMyPower

Copy link
Copy Markdown
Contributor Author

/pulsarbot run-failure-checks

1 similar comment
@BewareMyPower

Copy link
Copy Markdown
Contributor Author

/pulsarbot run-failure-checks

@codelipenghui codelipenghui left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks good to me. I think the producer side also has a similar problem? If there are producers or consumers connect to the topic with bytes schema, then when a new producer connect with avro schema, I think the schema of the topic will change to avro. This will break the existing producers/consumers, could you please also help push a separate PR to fix it?

@codelipenghui
codelipenghui requested a review from zymap March 10, 2021 07:04
@codelipenghui

Copy link
Copy Markdown
Contributor

@congbobo184 @gaoran10 @limingnihao Could you please also help review this PR? You are working on the Pulsar schema currently, make sure we are on the same page.

@eolivelli eolivelli left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good.
I left a little suggestion.

Apart from that, can you please add the same test for non persistent topics and ensure that the behaviour is consistent?

@congbobo184

Copy link
Copy Markdown
Contributor

LGTM!

@BewareMyPower

Copy link
Copy Markdown
Contributor Author

I've fixed the same issue for non-persistent topics, PTAL @eolivelli

@BewareMyPower

BewareMyPower commented Mar 10, 2021

Copy link
Copy Markdown
Contributor Author

I think the producer side also has a similar problem? If there are producers or consumers connect to the topic with bytes schema, then when a new producer connect with avro schema, I think the schema of the topic will change to avro.

@codelipenghui I'm not sure if it's the intended design for producer. Currently handleProducer uses tryAddSchema that is introduced in PIP-43 and #5165, while handleSubscribe uses addSchemaIfIdleOrCheckCompatible that is introduced in PIP-44 and #5227.

@gaoran10

gaoran10 commented Mar 10, 2021

Copy link
Copy Markdown
Contributor

the topic's schema should be changed to the consumer's schema even if it's active or has existed data

I have my doubts about the point "even if it has existed data", maybe this will cause the existed data can't be consumed because the schema changed.

@eolivelli eolivelli left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@BewareMyPower

Copy link
Copy Markdown
Contributor Author

@gaoran10 Sorry the PR description is outdated, I'll update it.

@BewareMyPower

Copy link
Copy Markdown
Contributor Author

This PR's description has been updated, PTAL again @gaoran10 .

@BewareMyPower

Copy link
Copy Markdown
Contributor Author

/pulsarbot run-failure-checks

1 similar comment
@BewareMyPower

Copy link
Copy Markdown
Contributor Author

/pulsarbot run-failure-checks

@codelipenghui

Copy link
Copy Markdown
Contributor

@codelipenghui I'm not sure if it's the intended design for producer. Currently handleProducer uses tryAddSchema that is introduced in PIP-43 and #5165, while handleSubscribe uses addSchemaIfIdleOrCheckCompatible that is introduced in PIP-44 and #5227.

@BewareMyPower PIP-43 also need to pass the compatibility check strategy, so we can apply the same rule for handling bytes schema at the producer side?

@BewareMyPower

Copy link
Copy Markdown
Contributor Author

@codelipenghui Okay, I'll take a look later.

@codelipenghui
codelipenghui merged commit 7f92ade into apache:master Mar 11, 2021
@BewareMyPower
BewareMyPower deleted the bewaremypower/fix-consumer-schema branch March 22, 2021 08:14
@codelipenghui codelipenghui added the cherry-picked/branch-2.7 Archived: 2.7 is end of life label Mar 23, 2021
codelipenghui pushed a commit that referenced this pull request Mar 23, 2021
)

Fixes #7728

When a consumer with a schema subscribes an empty topic without schema, the current check uses `isActive`, which only checks if the topic can be deleted. However, it should check if there's any connected producer or consumer of this topic. For current implementation, even if a topic has no active producers of consumers, the topic's subscription list may be not empty and `isActive` will return true. Then the schema of consumer won't be attached to the topic and it will throw an `IncompatibleSchemaException`.

- Check if the topic has active producers or consumers instead of whether it can be deleted.
- Add related tests.

(cherry picked from commit 7f92ade)
@Haaroon

Haaroon commented Nov 25, 2021

Copy link
Copy Markdown
Contributor

Which version was this fixed in? As of 2.8.1 via following the PublishFunction example, this still raises an error in localrun

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cherry-picked/branch-2.7 Archived: 2.7 is end of life release/2.7.2 type/bug The PR fixed a bug or issue reported a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Automatically created topics have no valid schema info

6 participants