-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Source Hubspot: Some incremental CRM objects and engagements #8887
Source Hubspot: Some incremental CRM objects and engagements #8887
Conversation
Related issue: #8344 |
Hi @lgomezm thank you very much for your contribution! Feel free to ping us when your PR is ready for review. Please also check our doc about publishing a new connector version. You basically have to bump the connector version in the |
Hi @alafanechere. I've just pushed some changes and bumped the version where you indicated. Also moved the PR to "Ready for review". Please let me know if there's anything I should provide on my side. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @lgomezm, I did a first quick review. I request changes because our integration tests are not passing (a simple unused import problem for the moment):
> Task :airbyte-integrations:connectors:source-hubspot:flakeCheck FAILED
[python] .venv/bin/python -m flake8 . --config /actions-runner/_work/airbyte/airbyte/tools/python/.flake8
./source_hubspot/client.py:11:1: F401 'source_hubspot.api.CRMObjectStream' imported but unused
Could you please make sure to make the acceptance test pass? I'll also ask for another reviewer because I'm not very familiar with this connector, which has a different implementation than the classic CDK-created connectors.
@lazebnyi I allowed myself to request a review from your side because git-blame showed me you are pretty active on this connector 😄 .
def _filter_dynamic_fields(self, records: Iterable) -> Iterable: | ||
"""Skip certain fields because they are too dynamic and change every call (timers, etc), | ||
see https://github.com/airbytehq/airbyte/issues/2397 | ||
""" | ||
for record in records: | ||
if isinstance(record, Mapping) and "properties" in record: | ||
for key in list(record["properties"].keys()): | ||
if key.startswith("hs_time_in"): | ||
record["properties"].pop(key) | ||
yield record |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you remove these hs_time_in
fields from ignored fields in acceptance-test-config
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We move it back and forth
As for me we don't need to remove data hs_*
fields from response
Some customers complained about this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doc string of reverted back _filter_dynamic_fields
function points on issue #2397
which "says" that we don't need to filter-out hs_time_*
fields now
we DO filter-out this fileds on acceptance-test
level
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed this method again in 42b1f42 and can confirm it unit tests and acceptance tests still pass.
airbyte-integrations/connectors/source-hubspot/source_hubspot/api.py
Outdated
Show resolved
Hide resolved
airbyte-integrations/connectors/source-hubspot/source_hubspot/api.py
Outdated
Show resolved
Hide resolved
self.associations = associations or self.associations | ||
self._include_archived_only = include_archived_only | ||
|
||
def list(self, fields) -> Iterable: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know other classes are already defining a list
method but this is a reserved python word.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moreover, this function looks like the one defined in CRMObjectStream
. Do you think you could make them share a parent class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The list
function is actually being called when the connector's read
command is invoked. I think it's called internally, so even though it does not look good because it's a reserved word, I don't know if we can rename it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lgomezm I believe in this case, we can use some private naming like _list
and rename the main property method first, then change the name in all underlying calls. Is this possible, WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found where it was being invoked, so I renamed it in 42b1f42. I'm sorry I didn't know much about how these methods connected with the framework.
Hi @alafanechere. I've been updating the code as per your feedback. Here's the acceptance test results: Please let me know if you have any other comment. |
self.associations = associations or self.associations | ||
self._include_archived_only = include_archived_only | ||
|
||
def list(self, fields) -> Iterable: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lgomezm I believe in this case, we can use some private naming like _list
and rename the main property method first, then change the name in all underlying calls. Is this possible, WDYT?
def _filter_dynamic_fields(self, records: Iterable) -> Iterable: | ||
"""Skip certain fields because they are too dynamic and change every call (timers, etc), | ||
see https://github.com/airbytehq/airbyte/issues/2397 | ||
""" | ||
for record in records: | ||
if isinstance(record, Mapping) and "properties" in record: | ||
for key in list(record["properties"].keys()): | ||
if key.startswith("hs_time_in"): | ||
record["properties"].pop(key) | ||
yield record |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doc string of reverted back _filter_dynamic_fields
function points on issue #2397
which "says" that we don't need to filter-out hs_time_*
fields now
we DO filter-out this fileds on acceptance-test
level
@alafanechere @grubberr I think I have addressed all your comments so far. Please take a look again and let me know if there's anything else I should update. |
@lgomezm I have approved from my side but please get approval from rest of team because your change pretty big |
@alafanechere @lazebnyi This PR is ready for a second look. Please let me know of any comment! |
@alafanechere @lazebnyi Hi guys. This PR was updated a while ago. Please take a look at it when you get a chance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @lgomezm, thank for the changes you made. Could you please:
- bump the version in this file:
airbyte-config/init/src/main/resources/config/STANDARD_SOURCE_DEFINITION/36c891d9-4bd9-43ac-bad2-10e12756272c.json
? - Fix the conflict with
master
Once this is done and if acceptance tests are passing I'll take care of publishing the connector and merging the branch.
It'd be great if you could give me edit permission on this branch because I need to update thesource_specs.yaml
file after I publish the connector (by running./gradlew airbyte-config:init:processResources
).
42b1f42
to
0c78f6d
Compare
Hi @alafanechere I've just bumped the version as you mentioned, as well as fixed the conflicts with |
@alafanechere BTW, here are the acceptance tests still passing: |
@@ -13,7 +13,9 @@ | |||
CampaignStream, | |||
ContactListStream, | |||
ContactsListMembershipsStream, | |||
CRMSearchStream, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate import. Please run ./gradlew format
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 719b678.
@lgomezm the |
@marcosmarxm I think I've found and fixed the issue with acceptance tests in 9131635. Please give it a try again. |
9131635
to
a10db31
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We finally made it @lgomezm, thank you for your contribution and patience!
What
Adds a more efficient support for incremental updates on some Hubspot streams:
How
For CRM objects, it uses the CRM search endpoints, which allow filtering by different properties. In our case, we filter by the respective "last modified date".
For the engagements case, it uses the Get recent engagements endpoint.
Recommended reading order
client.py
api.py
🚨 User Impact 🚨
Are there any breaking changes? What is the end result perceived by the user? If yes, please merge this PR with the 🚨🚨 emoji so changelog authors can further highlight this if needed.
Pre-merge Checklist
Expand the relevant checklist and delete the others.
New Connector
Community member or Airbyter
airbyte_secret
./gradlew :airbyte-integrations:connectors:<name>:integrationTest
.README.md
bootstrap.md
. See description and examplesdocs/SUMMARY.md
docs/integrations/<source or destination>/<name>.md
including changelog. See changelog exampledocs/integrations/README.md
airbyte-integrations/builds.md
Airbyter
If this is a community PR, the Airbyte engineer reviewing this PR is responsible for the below items.
/test connector=connectors/<name>
command is passing./publish
command described hereUpdating a connector
Community member or Airbyter
airbyte_secret
./gradlew :airbyte-integrations:connectors:<name>:integrationTest
.README.md
bootstrap.md
. See description and examplesdocs/integrations/<source or destination>/<name>.md
including changelog. See changelog exampleAirbyter
If this is a community PR, the Airbyte engineer reviewing this PR is responsible for the below items.
/test connector=connectors/<name>
command is passing./publish
command described hereConnector Generator
-scaffold
in their name) have been updated with the latest scaffold by running./gradlew :airbyte-integrations:connector-templates:generator:testScaffoldTemplates
then checking in your changesThis change is