Karsten Bruns
10/18/2023, 6:57 AMkapa.ai
10/18/2023, 6:57 AMHttpStream in the HttpSubStream, you need to use the caching mechanism provided by Airbyte. Here's how it works: 1. If a request is made for the first time, the returned value will be written to disk. All requests made by the read_records method will be written to the cache file. 2. When the same request is made again, instead of making another HTTP request, the result will be read from disk. It is checked whether the required request is in the cache file, and if so, the data from this file is returned. However, if the check for the request's existence in the cache file fails, a new request will be made, and its result will be added to the cache file. To enable caching, you need to override the use_cache property of the HttpStream class to return True. Here's an example: python class Employees(HttpStream): ... @property def use_cache(self) -> bool: return True For child streams, there is an HttpSubStream class inheriting from HttpStream and overriding the stream_slices method that returns a generator of all parent entries. Here's an example: python class EmployeeDetails(HttpSubStream): ... To use caching in the parent/child relationship, perform the following steps: 1. Turn on parent stream caching by overriding the use_cache property. 2. Inherit child stream class from HttpSubStream class. For more details, you can refer to the [official documentation](https://docs.airbyte.com/connector-development/cdk-python/http-streams).Karsten Bruns
10/18/2023, 7:00 AMkapa.ai
10/18/2023, 7:00 AM/tmp/airbyte_local directory on the host machine running Airbyte. This applies to local destinations such as Local CSV, Local JSON, SQLite, and DuckDB. The destination_path will always start with /local whether it is specified by the user or not. Any directory nesting within /local will be mapped onto the local mount. The local mount is mounted by Docker onto LOCAL_ROOT, which means the /local is substituted by /tmp/airbyte_local by default. For example, if destination_path is set to /local/cars/models, then all data will be written to the /tmp/airbyte_local/cars/models directory on the host machine. Please ensure that Docker Desktop has access to /tmp (and /private on a MacOS, as /tmp has a symlink that points to /private. It will not work otherwise). You can allow it with "File sharing" in Settings -> Resources -> File sharing -> add the one or two above folder and hit the "Apply & restart" button. Sources: - [Local CSV](https://docs.airbyte.com/integrations/destinations/csv) - [Local JSON](https://docs.airbyte.com/integrations/destinations/local-json) - [SQLite](https://docs.airbyte.com/integrations/destinations/sqlite) - [DuckDB](https://docs.airbyte.com/integrations/destinations/duckdb) - [Browsing Output Logs](https://docs.airbyte.com/operator-guides/browsing-output-logs)Karsten Bruns
10/18/2023, 8:49 AMkapa.ai
10/18/2023, 8:49 AMkapa.ai
10/18/2023, 8:50 AMread_records, Read_pages and fetch_next_page implementations are not returning any records. Here are a few things you could check: 1. Check your read_records implementation: Ensure that your read_records method is correctly reading data from your source and yielding records. Remember, this method should output an iterable object containing records from the data source. Generators are recommended for their efficiency with regards to memory requirements. [source](https://docs.airbyte.com/connector-development/cdk-python/full-refresh-stream) 2. Check your Read_pages and fetch_next_page methods: Make sure these methods are correctly implemented to fetch and iterate over all the pages of data from your source. The framework works by iterating over all the partitions defined by the stream's partition router. For each partition, it submits a request to the partner API as defined by the requester, selects the records from the response, and repeats for as long as the paginator points to a next page. [source](https://docs.airbyte.com/connector-development/config-based/advanced-topics) 3. Check your stream's schema: Ensure that your stream's schema is correctly defined. This can be done either by storing the schema in the schemas/ directory or inline in the YAML file. [source](https://docs.airbyte.com/connector-development/config-based/tutorial/reading-data) 4. Debug your code: You can run the read operation with the --debug flag to print out debug information, including the outgoing request and its associated response. This can help you identify any issues with your code. [source](https://docs.airbyte.com/connector-development/config-based/tutorial/reading-data) If you've checked all of these and are still seeing "Read 0 records", it's possible that there's an issue with your data source or the way you're connecting to it. You might want to verify that your connection configuration is correct and that your data source contains the data you expect to read.Karsten Bruns
10/24/2023, 12:59 PMdef parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]:
res = response.json()
if response.status_code == 200:
yield from res.get("data", [])
elif response.status_code == 404:
return []
def read_records(
self,
sync_mode: SyncMode,
cursor_field: List[str] = None,
stream_slice: Mapping[str, Any] = None,
stream_state: Mapping[str, Any] = None,
) -> Iterable[StreamData]:
yield from self._read_pages(
lambda req, res, state, _slice: self.parse_response(res, stream_slice=_slice, stream_state=state), stream_slice, stream_state
)
def _read_pages(
self,
records_generator_fn: Callable[
[requests.PreparedRequest, requests.Response, Mapping[str, Any], Mapping[str, Any]], Iterable[StreamData]
],
stream_slice: Mapping[str, Any] = None,
stream_state: Mapping[str, Any] = None,
) -> Iterable[StreamData]:
stream_state = stream_state or {}
pagination_complete = False
next_page_token = None
while not pagination_complete:
request, response = self._fetch_next_page(stream_slice, stream_state, next_page_token)
yield from records_generator_fn(request, response, stream_state, stream_slice)
next_page_token = self.next_page_token(response)
if not next_page_token:
pagination_complete = True
# Always return an empty generator just in case no records were ever yielded
yield from []
def _fetch_next_page(
self, stream_slice: Mapping[str, Any] = None, stream_state: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None
) -> Tuple[requests.PreparedRequest, requests.Response]:
request_headers = self.request_headers(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token)
request = self._create_prepared_request(
path=self.path(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token),
headers=dict(request_headers, **self.authenticator.get_auth_header()),
params=self.request_params(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token),
json=self.request_body_json(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token),
data=self.request_body_data(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token),
)
request_kwargs = self.request_kwargs(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token)
response = self._send_request(request, request_kwargs)
return request, responsekapa.ai
10/24/2023, 12:59 PMkapa.ai
10/24/2023, 1:00 PMparse_response method. In the parse_response method, you are yielding from res.get("data", []). This means that the method is expecting the records to be under the "data" key in the response JSON. If the records are not under this key, it would result in "Read 0 records" message. Here are a few things you could check: 1. Check the structure of your API response: Ensure that the records are indeed under the "data" key in the response JSON. If they are under a different key, you should modify the parse_response method to yield from the correct key. 2. Check the status code: You're only yielding records if the status code is 200. If the API is returning a different status code, no records would be yielded. You can print the status code to check this. 3. Check the pagination: In the _read_pages method, you're using a next_page_token to handle pagination. Ensure that this is being correctly set and used. If the next_page_token is not correctly set, it might result in the same page being read repeatedly, or some pages being skipped. 4. Check the yield from [] line: At the end of the _read_pages method, you're yielding from an empty list. This line will yield no records. If your pagination logic is causing this line to be hit before all pages have been read, it would result in "Read 0 records" message. You might want to move this line to a different location, or remove it if it's not needed. If you've checked all of these and are still seeing "Read 0 records", it's possible that there's an issue with your data source or the way you're connecting to it. You might want to verify that your connection configuration is correct and that your data source contains the data you expect to read.Karsten Bruns
10/24/2023, 1:10 PMkapa.ai
10/24/2023, 1:10 PMkapa.ai
10/24/2023, 1:11 PM