From 406fe92b39d24668ef8b9a23e45b8089f7f6e1d3 Mon Sep 17 00:00:00 2001 From: karranikhilreddy99 Date: Wed, 11 Jun 2025 20:20:21 -0500 Subject: [PATCH 1/4] Add Starburst Scheduler Guide --- ecosystem/Starburst-Scheduler.md | 205 +++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 ecosystem/Starburst-Scheduler.md diff --git a/ecosystem/Starburst-Scheduler.md b/ecosystem/Starburst-Scheduler.md new file mode 100644 index 0000000000..3dfa9b755a --- /dev/null +++ b/ecosystem/Starburst-Scheduler.md @@ -0,0 +1,205 @@ +--- + +```markdown +# Starburst Scheduler: Python Pip Package to Automate Starburst.io SQL Queries + + +## Meta Description + +Starburst Scheduler is an open-source Python package that enables you to run and schedule SQL queries on Starburst Trino OSS and Starburst Enterprise. Automate Starburst queries, monitor cluster health, and integrate with Slack and Mattermost — all from a simple CLI tool. Ideal for DevOps, data engineering, and CI/CD pipelines. + + +## Introduction + +In today’s data-driven organizations, query automation and monitoring are critical for maintaining healthy data platforms and delivering reliable insights. + +**Common questions:** + +- How do I automate important queries to monitor our Starburst clusters? +- How do I run scheduled reports and send alerts to Slack or Mattermost? + +While tools like Apache Airflow exist, I wanted something much lighter and faster — something that could run from the command line or within CI/CD pipelines. + +That’s why I built **Starburst Scheduler** — an open-source Python package that enables anyone to run and schedule Starburst queries with just a few commands. + +In this article, I’ll walk you through: + +- What is Starburst +- Why I built this tool +- How Starburst Scheduler works +- How you can use it +- Planned enhancements +- How you can contribute + +## What is Starburst? + +Starburst is a modern distributed query engine built on top of Trino. + +It allows users to run high-performance SQL queries across multiple data sources, including: + +- Data lakes (S3, ADLS) +- Hive +- Delta Lake +- PostgreSQL +- MySQL +- Oracle +- Kafka +- And more + +It powers interactive analytics and data mesh architectures in modern enterprises. + +### Starburst Galaxy vs Starburst Enterprise vs OSS + +- **Starburst Galaxy** → fully managed SaaS offering — ideal for cloud-native deployments. +- **Starburst Enterprise** → self-managed version — deployable on Kubernetes, OpenShift, or on-premises. +- **OSS (Open Source Trino)** → provides the core engine but lacks the enterprise features, support, and integrations. + +## The Need for Automation + +In production data platforms, teams often need to: + +- Monitor cluster health via scheduled queries +- Run daily reports and publish results +- Detect data anomalies and trigger alerts +- Integrate query result with team communication tools (Slack, Mattermost) + +While Starburst provides an excellent UI, it does not natively offer lightweight scheduling. + +Apache Airflow is an option, but requires significant setup. +Cron jobs are too basic and hard to manage at scale. + +That’s why I built this simple CLI tool. + +## What is Starburst Scheduler? + +Starburst Scheduler is an open-source Python package that allows you to: + +- Run Starburst queries from the command line +- Schedule Starburst queries to run at regular intervals (seconds, minutes, hours, days) +- (Coming soon) Send results to Slack, Mattermost, email + +It is ideal for: + +- DevOps engineers monitoring Starburst clusters +- Data engineers automating reports +- Platform engineers adding checks to CI/CD pipelines + +It requires no additional servers or orchestration systems. + +## How It Works + +Starburst Scheduler is built using: + +- `pystarburst` — the official Python client for Starburst +- `schedule` — a lightweight job scheduling library +- `click` — for building powerful command-line interfaces + +### Architecture + +``` + ++----------------------+ +------------------+ +\| CLI (Click) | --> | StarburstConnector| +\| | +------------------+ +\| run-query | --> Connect --> Run query +\| schedule-query | --> Connect --> Schedule query ++----------------------+ | +v ++--------------------+ +\| QueryScheduler | +\| (schedule library) | ++--------------------+ + +```` + +## Features + +- Run SQL queries directly from the CLI +- Schedule queries at regular intervals (seconds, minutes, hours, days) +- Compatible with both Starburst Galaxy and Starburst Enterprise +- Works well in CI/CD pipelines (GitHub Actions, Jenkins, etc.) +- Lightweight — no servers required +- (Coming soon) Slack/Mattermost integration — automated alerts +- MIT Licensed — fully open-source + +## Installation + +```bash +pip install starburst_scheduler +```` + +## Usage + +### Run a Single Query + +```bash +starburst-scheduler run-query --host --port --user --password --catalog sample --schema burstbank --query "SELECT * FROM system.runtime.nodes" +``` + +### Schedule a Query + +```bash +starburst-scheduler schedule-query --host --port --user --password --catalog sample --schema burstbank --query "SELECT * FROM system.runtime.nodes" --frequency 60 --time-unit seconds +``` + +## Planned Enhancements + +### Slack & Mattermost integration + +Automatically post query results to team chat when queries run. +Example: monitor active queries, cluster status, send alerts. + +### CSV/JSON output + +Option to save query results to CSV or JSON for downstream use in data pipelines. + +### Advanced scheduling + +Support for cron expressions, weekly/monthly jobs. + +### Email notifications + +Option to send query results via email. + +### Error alerting + +Notify users when query runs fail. + +## Example Use Cases + +### Cluster Health Monitoring + +Run this query every 5 minutes: + +```sql +SELECT * FROM system.runtime.nodes +``` + +Send the results to Slack to monitor Starburst node status. + +### Daily Report Automation + +Schedule a complex query to run daily at 6 AM, save the results as CSV, and email them to the BI team. + +## How to Contribute + +GitHub: [https://github.com/karranikhilreddy99/starburst\_scheduler](https://github.com/karranikhilreddy99/starburst_scheduler) + +* Issues and PRs welcome +* If you like the project, please star it on GitHub + +## Conclusion + +Starburst Scheduler fills an important gap: + +* It allows you to automate Starburst queries without setting up heavy orchestration tools +* It is ideal for DevOps, data engineering, and CI/CD pipelines +* It is fully open-source and easy to extend + +In the future, I plan to add Slack/Mattermost integrations, advanced scheduling, and more. + +If you use Starburst and want a lightweight scheduling tool — give **Starburst Scheduler** a try. + +GitHub: [https://github.com/karranikhilreddy99/starburst\_scheduler](https://github.com/karranikhilreddy99/starburst_scheduler) + +--- \ No newline at end of file From 100cc45e8598041fd6eaebb57bb023fb1fa9127d Mon Sep 17 00:00:00 2001 From: karranikhilreddy99 Date: Wed, 11 Jun 2025 21:25:42 -0500 Subject: [PATCH 2/4] Update Starburst-Scheduler.md Fix YAML error and improve formatting. --- ecosystem/Starburst-Scheduler.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ecosystem/Starburst-Scheduler.md b/ecosystem/Starburst-Scheduler.md index 3dfa9b755a..e8900eb155 100644 --- a/ecosystem/Starburst-Scheduler.md +++ b/ecosystem/Starburst-Scheduler.md @@ -1,3 +1,8 @@ +--- +Title: "Starburst Scheduler: Python Pip Package to Automate Starburst.io SQL Queries" + +Description: "Automate Starburst.io SQL queries using the Starburst Scheduler Python package." + --- ```markdown @@ -201,5 +206,3 @@ In the future, I plan to add Slack/Mattermost integrations, advanced scheduling, If you use Starburst and want a lightweight scheduling tool — give **Starburst Scheduler** a try. GitHub: [https://github.com/karranikhilreddy99/starburst\_scheduler](https://github.com/karranikhilreddy99/starburst_scheduler) - ---- \ No newline at end of file From 822451525692a4858fb7b9e8cf97cf93df3b1fcc Mon Sep 17 00:00:00 2001 From: karranikhilreddy99 Date: Thu, 12 Jun 2025 23:24:33 -0500 Subject: [PATCH 3/4] Add Trino Scheduler (Starburst-compatible) to addons in tools.yml and remove standalone doc --- _data/tools.yml | 6 + ecosystem/Starburst-Scheduler.md | 208 ------------------------------- 2 files changed, 6 insertions(+), 208 deletions(-) delete mode 100644 ecosystem/Starburst-Scheduler.md diff --git a/_data/tools.yml b/_data/tools.yml index f3b2617217..ea79f211ee 100644 --- a/_data/tools.yml +++ b/_data/tools.yml @@ -1958,6 +1958,12 @@ url: https://www.youtube.com/watch?v=2qwBcKmQSn0 - urltext: Announcement blog post url: /blog/2023/09/28/trino-gateway +- name: Trino Scheduler (Starburst-compatible) + category: addons + owner: community + description: Python CLI tool to automate and schedule Trino queries. Works with Trino OSS, Starburst Enterprise, and Starburst Galaxy. Supports multi-cluster usage and Mattermost alert integration. + link: https://github.com/karranikhilreddy99/starburst_scheduler + - name: Unity Catalog anchor: unity-catalog category: data-lake diff --git a/ecosystem/Starburst-Scheduler.md b/ecosystem/Starburst-Scheduler.md deleted file mode 100644 index e8900eb155..0000000000 --- a/ecosystem/Starburst-Scheduler.md +++ /dev/null @@ -1,208 +0,0 @@ ---- -Title: "Starburst Scheduler: Python Pip Package to Automate Starburst.io SQL Queries" - -Description: "Automate Starburst.io SQL queries using the Starburst Scheduler Python package." - ---- - -```markdown -# Starburst Scheduler: Python Pip Package to Automate Starburst.io SQL Queries - - -## Meta Description - -Starburst Scheduler is an open-source Python package that enables you to run and schedule SQL queries on Starburst Trino OSS and Starburst Enterprise. Automate Starburst queries, monitor cluster health, and integrate with Slack and Mattermost — all from a simple CLI tool. Ideal for DevOps, data engineering, and CI/CD pipelines. - - -## Introduction - -In today’s data-driven organizations, query automation and monitoring are critical for maintaining healthy data platforms and delivering reliable insights. - -**Common questions:** - -- How do I automate important queries to monitor our Starburst clusters? -- How do I run scheduled reports and send alerts to Slack or Mattermost? - -While tools like Apache Airflow exist, I wanted something much lighter and faster — something that could run from the command line or within CI/CD pipelines. - -That’s why I built **Starburst Scheduler** — an open-source Python package that enables anyone to run and schedule Starburst queries with just a few commands. - -In this article, I’ll walk you through: - -- What is Starburst -- Why I built this tool -- How Starburst Scheduler works -- How you can use it -- Planned enhancements -- How you can contribute - -## What is Starburst? - -Starburst is a modern distributed query engine built on top of Trino. - -It allows users to run high-performance SQL queries across multiple data sources, including: - -- Data lakes (S3, ADLS) -- Hive -- Delta Lake -- PostgreSQL -- MySQL -- Oracle -- Kafka -- And more - -It powers interactive analytics and data mesh architectures in modern enterprises. - -### Starburst Galaxy vs Starburst Enterprise vs OSS - -- **Starburst Galaxy** → fully managed SaaS offering — ideal for cloud-native deployments. -- **Starburst Enterprise** → self-managed version — deployable on Kubernetes, OpenShift, or on-premises. -- **OSS (Open Source Trino)** → provides the core engine but lacks the enterprise features, support, and integrations. - -## The Need for Automation - -In production data platforms, teams often need to: - -- Monitor cluster health via scheduled queries -- Run daily reports and publish results -- Detect data anomalies and trigger alerts -- Integrate query result with team communication tools (Slack, Mattermost) - -While Starburst provides an excellent UI, it does not natively offer lightweight scheduling. - -Apache Airflow is an option, but requires significant setup. -Cron jobs are too basic and hard to manage at scale. - -That’s why I built this simple CLI tool. - -## What is Starburst Scheduler? - -Starburst Scheduler is an open-source Python package that allows you to: - -- Run Starburst queries from the command line -- Schedule Starburst queries to run at regular intervals (seconds, minutes, hours, days) -- (Coming soon) Send results to Slack, Mattermost, email - -It is ideal for: - -- DevOps engineers monitoring Starburst clusters -- Data engineers automating reports -- Platform engineers adding checks to CI/CD pipelines - -It requires no additional servers or orchestration systems. - -## How It Works - -Starburst Scheduler is built using: - -- `pystarburst` — the official Python client for Starburst -- `schedule` — a lightweight job scheduling library -- `click` — for building powerful command-line interfaces - -### Architecture - -``` - -+----------------------+ +------------------+ -\| CLI (Click) | --> | StarburstConnector| -\| | +------------------+ -\| run-query | --> Connect --> Run query -\| schedule-query | --> Connect --> Schedule query -+----------------------+ | -v -+--------------------+ -\| QueryScheduler | -\| (schedule library) | -+--------------------+ - -```` - -## Features - -- Run SQL queries directly from the CLI -- Schedule queries at regular intervals (seconds, minutes, hours, days) -- Compatible with both Starburst Galaxy and Starburst Enterprise -- Works well in CI/CD pipelines (GitHub Actions, Jenkins, etc.) -- Lightweight — no servers required -- (Coming soon) Slack/Mattermost integration — automated alerts -- MIT Licensed — fully open-source - -## Installation - -```bash -pip install starburst_scheduler -```` - -## Usage - -### Run a Single Query - -```bash -starburst-scheduler run-query --host --port --user --password --catalog sample --schema burstbank --query "SELECT * FROM system.runtime.nodes" -``` - -### Schedule a Query - -```bash -starburst-scheduler schedule-query --host --port --user --password --catalog sample --schema burstbank --query "SELECT * FROM system.runtime.nodes" --frequency 60 --time-unit seconds -``` - -## Planned Enhancements - -### Slack & Mattermost integration - -Automatically post query results to team chat when queries run. -Example: monitor active queries, cluster status, send alerts. - -### CSV/JSON output - -Option to save query results to CSV or JSON for downstream use in data pipelines. - -### Advanced scheduling - -Support for cron expressions, weekly/monthly jobs. - -### Email notifications - -Option to send query results via email. - -### Error alerting - -Notify users when query runs fail. - -## Example Use Cases - -### Cluster Health Monitoring - -Run this query every 5 minutes: - -```sql -SELECT * FROM system.runtime.nodes -``` - -Send the results to Slack to monitor Starburst node status. - -### Daily Report Automation - -Schedule a complex query to run daily at 6 AM, save the results as CSV, and email them to the BI team. - -## How to Contribute - -GitHub: [https://github.com/karranikhilreddy99/starburst\_scheduler](https://github.com/karranikhilreddy99/starburst_scheduler) - -* Issues and PRs welcome -* If you like the project, please star it on GitHub - -## Conclusion - -Starburst Scheduler fills an important gap: - -* It allows you to automate Starburst queries without setting up heavy orchestration tools -* It is ideal for DevOps, data engineering, and CI/CD pipelines -* It is fully open-source and easy to extend - -In the future, I plan to add Slack/Mattermost integrations, advanced scheduling, and more. - -If you use Starburst and want a lightweight scheduling tool — give **Starburst Scheduler** a try. - -GitHub: [https://github.com/karranikhilreddy99/starburst\_scheduler](https://github.com/karranikhilreddy99/starburst_scheduler) From a391ca00140a54f3d5fb2539757f597ed4cb4a97 Mon Sep 17 00:00:00 2001 From: karranikhilreddy99 Date: Fri, 13 Jun 2025 00:38:09 -0500 Subject: [PATCH 4/4] Address review feedback: update Trino Scheduler entry with logo and links --- _data/tools.yml | 14 ++++++++++---- assets/images/logos/trino-scheduler.png | Bin 0 -> 15697 bytes 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 assets/images/logos/trino-scheduler.png diff --git a/_data/tools.yml b/_data/tools.yml index ea79f211ee..781dec179b 100644 --- a/_data/tools.yml +++ b/_data/tools.yml @@ -1958,12 +1958,18 @@ url: https://www.youtube.com/watch?v=2qwBcKmQSn0 - urltext: Announcement blog post url: /blog/2023/09/28/trino-gateway -- name: Trino Scheduler (Starburst-compatible) +- name: Trino Scheduler category: addons owner: community - description: Python CLI tool to automate and schedule Trino queries. Works with Trino OSS, Starburst Enterprise, and Starburst Galaxy. Supports multi-cluster usage and Mattermost alert integration. - link: https://github.com/karranikhilreddy99/starburst_scheduler - + logo: /assets/images/logos/trino-scheduler.png + description: | + Trino Scheduler is a Python command line tool to automate and + schedule Trino queries. Works with Trino, Starburst Enterprise, and + Starburst Galaxy. Supports multi-cluster usage and Mattermost alert + integration. + links: + - urltext: GitHub Repository + url: https://github.com/karranikhilreddy99/starburst_scheduler - name: Unity Catalog anchor: unity-catalog category: data-lake diff --git a/assets/images/logos/trino-scheduler.png b/assets/images/logos/trino-scheduler.png new file mode 100644 index 0000000000000000000000000000000000000000..c879ad1a058df40bce76f3968d7e7215596379b6 GIT binary patch literal 15697 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 b*~Q52_y5nNy9mSm#{i_o<;7}64TJs%-xxW5 literal 0 HcmV?d00001