diff --git a/api_examples/hsfs/feature_group_change_notification_cdc.ipynb b/api_examples/hsfs/feature_group_change_notification_cdc.ipynb new file mode 100644 index 00000000..238f147e --- /dev/null +++ b/api_examples/hsfs/feature_group_change_notification_cdc.ipynb @@ -0,0 +1,253 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9e9da978", + "metadata": {}, + "source": [ + "![Screenshot from 2022-06-16 14-24-57.png](data:image/png;base64,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)" + ] + }, + { + "cell_type": "markdown", + "id": "55b19afd", + "metadata": {}, + "source": [ + "## 💽 CDC (change data notification) for Feature Groups \n", + "\n", + "This notebook shows you how to write a CDC client that subscribes to changes to an Online Feature Group\n", + "\n", + "The notebook performs the following steps:\n", + "\n", + "1. Create the Kafka topic in your Hopsworks Project for the CDC notifications for the Fetaure Group\n", + "2. Create the Feature Group, providing the name of the CDC notification topic you just created\n", + "3. Insert some data into the feature group\n", + "4. Run a Kafka Client that consume the changes to the Feature Group (from the notification topic)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "46ee5e6e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Connected. Call `.close()` to terminate connection gracefully.\n", + "\n", + "Logged in to project, explore it here https://hopsworks0.logicalclocks.com/p/2167\n", + "Connected. Call `.close()` to terminate connection gracefully.\n" + ] + } + ], + "source": [ + "import hopsworks\n", + "import pandas as pd\n", + "\n", + "project = hopsworks.login()\n", + "fs = project.get_feature_store()" + ] + }, + { + "cell_type": "markdown", + "id": "c7b04834", + "metadata": {}, + "source": [ + "### Create the CDC Kafka Topic for Notifications" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b951fca3", + "metadata": {}, + "outputs": [], + "source": [ + "feature_group_name = \"cdc\"\n", + "notification_topic = f\"{feature_group_name}_notification\"\n", + "partitions = 10\n", + "\n", + "if not any(topic.name == notification_topic for topic in project.get_kafka_api().get_topics()):\n", + " project.get_kafka_api().create_topic(notification_topic, None, None, partitions=partitions)" + ] + }, + { + "cell_type": "markdown", + "id": "c5b95586", + "metadata": {}, + "source": [ + "### Create the Feature Group, providing the CDC topic name " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "ba5fc19f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Feature Group created successfully, explore it at \n", + "https://hopsworks0.logicalclocks.com/p/2167/fs/2115/fg/2066\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7c478f19a06247b38633c023263993df", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Uploading Dataframe: 0.00% | | Rows 0/10 | Elapsed Time: 00:00 | Remaining Time: ?" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Launching job: cdc_1_offline_fg_materialization\n", + "Job started successfully, you can follow the progress at \n", + "https://hopsworks0.logicalclocks.com/p/2167/jobs/named/cdc_1_offline_fg_materialization/executions\n" + ] + }, + { + "data": { + "text/plain": [ + "(, None)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fg = fs.get_or_create_feature_group(name=feature_group_name, \n", + " version=1, \n", + " primary_key=[\"id\"], \n", + " online_enabled=True, \n", + " notification_topic_name=notification_topic)\n", + "\n", + "size = 10\n", + "fg_data = {'id': range(0, size), 'text': \"test\"}\n", + "fg_df = pd.DataFrame.from_dict(fg_data)\n", + "fg.insert(fg_df)" + ] + }, + { + "cell_type": "markdown", + "id": "150370b6", + "metadata": {}, + "source": [ + "### Reading the contents of CDC topic" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "4444e032", + "metadata": {}, + "outputs": [], + "source": [ + "import confluent_kafka\n", + "\n", + "# after assignment make consumer read from the begginning\n", + "def my_assign(consumer, partitions):\n", + " for partition in partitions:\n", + " partition.offset = confluent_kafka.OFFSET_BEGINNING\n", + " consumer.assign(partitions)\n", + "\n", + "storage_connector = fs._storage_connector_api.get_kafka_connector(fs.id)\n", + "\n", + "config = storage_connector.confluent_options()\n", + "# You have to define a 'group.id'. If multiple consumers with the same group.id are subscribed to the same topic,\n", + "# they will share consupmtions of its msgs\n", + "config[\"group.id\"] = feature_group_name\n", + "consumer = confluent_kafka.Consumer(config)\n", + "consumer.subscribe([notification_topic], on_assign=my_assign)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "09cc84f2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "b'{\"projectId\":2167,\"featureStoreId\":2115,\"featureGroupId\":2066,\"entry\":{\"id\":\"6\",\"text\":\"test\"},\"featureViews\":[]}'\n", + "b'{\"projectId\":2167,\"featureStoreId\":2115,\"featureGroupId\":2066,\"entry\":{\"id\":\"2\",\"text\":\"test\"},\"featureViews\":[]}'\n", + "b'{\"projectId\":2167,\"featureStoreId\":2115,\"featureGroupId\":2066,\"entry\":{\"id\":\"5\",\"text\":\"test\"},\"featureViews\":[]}'\n", + "b'{\"projectId\":2167,\"featureStoreId\":2115,\"featureGroupId\":2066,\"entry\":{\"id\":\"7\",\"text\":\"test\"},\"featureViews\":[]}'\n", + "b'{\"projectId\":2167,\"featureStoreId\":2115,\"featureGroupId\":2066,\"entry\":{\"id\":\"0\",\"text\":\"test\"},\"featureViews\":[]}'\n", + "b'{\"projectId\":2167,\"featureStoreId\":2115,\"featureGroupId\":2066,\"entry\":{\"id\":\"9\",\"text\":\"test\"},\"featureViews\":[]}'\n", + "b'{\"projectId\":2167,\"featureStoreId\":2115,\"featureGroupId\":2066,\"entry\":{\"id\":\"3\",\"text\":\"test\"},\"featureViews\":[]}'\n", + "b'{\"projectId\":2167,\"featureStoreId\":2115,\"featureGroupId\":2066,\"entry\":{\"id\":\"8\",\"text\":\"test\"},\"featureViews\":[]}'\n", + "b'{\"projectId\":2167,\"featureStoreId\":2115,\"featureGroupId\":2066,\"entry\":{\"id\":\"4\",\"text\":\"test\"},\"featureViews\":[]}'\n", + "b'{\"projectId\":2167,\"featureStoreId\":2115,\"featureGroupId\":2066,\"entry\":{\"id\":\"1\",\"text\":\"test\"},\"featureViews\":[]}'\n", + "done\n" + ] + } + ], + "source": [ + "run = True\n", + "while run:\n", + " msg = consumer.poll(timeout=10)\n", + " if msg is not None:\n", + " print(msg.value())\n", + " else:\n", + " run = False\n", + "print(\"done\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "ed56a62d", + "metadata": {}, + "outputs": [], + "source": [ + "consumer.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60e148c0", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}