fix: respect whether a sink is enabled when dumping data to ClickHouse - #251
Conversation
|
Thanks for the pull request, @ccantillo! This repository is currently maintained by Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review. 🔘 Get product approvalIf you haven't already, check this list to see if your contribution needs to go through the product review process.
🔘 Provide contextTo help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:
🔘 Get a green buildIf one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green. DetailsWhere can I find more information?If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources: When can I expect my changes to be merged?Our goal is to get community contributions seen and reviewed as efficiently as possible. However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:
💡 As a result it may take up to several weeks or months to complete a review and merge your PR. |
felipemontoya
left a comment
There was a problem hiding this comment.
This approach is more elegant than the tutor-contrib-aspects pr. I like it. However I am unsure the message is correct.
From your description, the tutor command is tutor local do dump-data-to-clickhouse --options "--object user_profile"
Which would turn EVENT_SINK_CLICKHOUSE_{options['object'].upper()}_ENABLED into EVENT_SINK_CLICKHOUSE_USER_PROFILE_ENABLED. But the actual config value is passed as: EVENT_SINK_CLICKHOUSE_PII_MODELS.
Could you please double check and explain why your approach works.
689a54d to
1d623b9
Compare
Thanks for the review @felipemontoya. Tutor renders two different things into the LMS settings ( # line 20 — always, no condition
EVENT_SINK_CLICKHOUSE_PII_MODELS = {{ EVENT_SINK_PII_MODELS }}
# lines 76-78 — only when ASPECTS_ENABLE_PII is true
{% if ASPECTS_ENABLE_PII %}# User PII models
{% for model in EVENT_SINK_PII_MODELS %}EVENT_SINK_CLICKHOUSE_{{model.upper()}}_ENABLED = True
{% endfor %}{% endif %}The one you spotted ( The per-model flag is the one with the state, and that's what getattr(settings, f"{WAFFLE_FLAG_NAMESPACE.upper()}_{cls.model.upper()}_ENABLED", False)
# "EVENT_SINK_CLICKHOUSE" + "USER_PROFILE" + "_ENABLED"So with I checked on a running instance rather than just reading the code. Before: After: |
|
Thanks for the updates to the PR @ccantillo. I think this is ready for your review @saraburns1 |
The dump_data_to_clickhouse management command dumped whatever object it was given, ignoring EVENT_SINK_CLICKHOUSE_<MODEL>_ENABLED, while the Celery task in tasks.py already gates on Sink.is_enabled(). This meant an instance that had opted out of PII collection could still populate the user_profile and external_id tables via a manual dump. A disabled sink now logs at info level and dumps nothing, matching the behaviour of the task.
4d9c94e to
b6a28f2
Compare
|
I meant to rebase, but clicked on merge main instead. I had to actually pull/rebase/force to get it in line. |
dump_data_to_clickhouseshould respect whether a sink is enabledSummary
The
dump_data_to_clickhousemanagement command now checksSink.is_enabled()before dumping. If the sink for the requested
--objectis disabled it logs atinfo level and dumps nothing, which is what the Celery task already does.
Why
The async path already gates on this, in
platform_plugin_aspects/tasks.py:The management command did not.
handle()went straight from--objecttoModelBaseSink.get_sink_by_model_name(...)and dumped unconditionally, soEVENT_SINK_CLICKHOUSE_<MODEL>_ENABLEDwas honoured for signal-driven syncs butsilently ignored for manual ones.
The practical consequence is on the PII models.
tutor-contrib-aspectsonlysets
EVENT_SINK_CLICKHOUSE_USER_PROFILE_ENABLED/..._EXTERNAL_ID_ENABLEDwhen
ASPECTS_ENABLE_PIIis true, so an operator who has deliberately opted outof PII collection could still populate the
user_profileandexternal_idtables in ClickHouse by running the command by hand. Verified on a live
instance: with
ASPECTS_ENABLE_PII=false, running./manage.py lms dump_data_to_clickhouse --object user_profileloggedDumped 4 objects to ClickHouseand added those rows toevent_sink.user_profile.Where the enabled flag comes from
tutor-contrib-aspectsrenders two different settings into the LMS, and onlyone of them carries the on/off state:
EVENT_SINK_CLICKHOUSE_PII_MODELSis rendered unconditionally. Its onlyruntime use is
UserRetirementSink(sinks/user_retire_sink.py:37), whichreads it to delete PII rows when a user retires — it describes where PII
lives, not whether it is being collected.
EVENT_SINK_CLICKHOUSE_<MODEL>_ENABLEDis rendered only whenASPECTS_ENABLE_PIIis true. This is the oneis_enabled()reads(
sinks/base_sink.py:346), building the name at runtime fromWAFFLE_FLAG_NAMESPACEand the sink'smodel.So with
ASPECTS_ENABLE_PII=falsethe per-model flag is simply absent andgetattr(..., False)reports the sink as disabled. This is also the mechanismthe README documents for toggling sinks, via that setting or the
event_sink_clickhouse.<model>.enabledwaffle flag.Note on the tests
The existing tests in this file drive a
DummySink, whichis_enabled()wouldreport as disabled — it has neither a model config entry nor an enabled setting.
Rather than weaken the new check to keep them green, the two existing test
functions are now decorated with an
override_settingsthat registersdummyin
EVENT_SINK_CLICKHOUSE_MODEL_CONFIGand setsEVENT_SINK_CLICKHOUSE_DUMMY_ENABLED = True, which is what those tests werealready assuming implicitly. A new test covers the disabled case, patching
WaffleFlag.is_enabledthe same waysinks/tests/test_base_sink.pydoes.Test plan
pytest platform_plugin_aspects— 110 passed, including the new test.black --checkandisort --check-onlyclean on both files.pylintproduces no new warnings: the message set for the test file isbyte-identical before and after this change (the remaining ones are
pre-existing).
AI disclosure
Claude (Anthropic) was used to trace the difference between the task and command
code paths and to draft this change and its tests. I reviewed and understand it:
it is a single
is_enabled()guard mirroring an existing pattern in this repo,plus test setup that makes the dummy sink's enabled state explicit. I ran the
test suite and the quality checks myself, and confirmed the underlying problem on
a live instance before writing the fix.