-
Notifications
You must be signed in to change notification settings - Fork 0
Added materialized view and duplicated v2 Tinybird endpoints #51
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
base: coderabbit_full_base_added_materialized_view_and_duplicated_v2_tinybird_endpoints_pr13
Are you sure you want to change the base?
Changes from all commits
b9d462c
e168280
59a7a1f
6492b0d
acce83e
a3edefd
3ef63ca
960c54d
b9a4376
4601200
e64a779
0502c8e
6f89a02
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -13,7 +13,11 @@ export const getStatEndpointUrl = (config?: StatsConfig | null, endpointName?: s | |||||||||||||||||
| } else { | ||||||||||||||||||
| baseUrl = config.endpoint || ''; | ||||||||||||||||||
| } | ||||||||||||||||||
| return `${baseUrl}/v0/pipes/${endpointName}.json?${params}`; | ||||||||||||||||||
|
|
||||||||||||||||||
| // Append version suffix if provided (e.g., "v2" -> "api_kpis_v2") | ||||||||||||||||||
| const finalEndpointName = config.version ? `${config.version}_${endpointName}` : endpointName; | ||||||||||||||||||
|
|
||||||||||||||||||
| return `${baseUrl}/v0/pipes/${finalEndpointName}.json?${params}`; | ||||||||||||||||||
|
Comment on lines
+17
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix versioned endpoint naming to match v2 pipe suffixes. Current logic builds 🔧 Proposed fix- // Append version suffix if provided (e.g., "v2" -> "api_kpis_v2")
- const finalEndpointName = config.version ? `${config.version}_${endpointName}` : endpointName;
+ // Append version suffix if provided (e.g., "v2" -> "api_kpis_v2")
+ const finalEndpointName = config.version ? `${endpointName}_${config.version}` : endpointName;📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| export const getToken = () => { | ||||||||||||||||||
|
|
||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| SCHEMA > | ||
| `site_uuid` LowCardinality(String), | ||
| `session_id` String, | ||
| `pageviews` AggregateFunction(count, UInt64), | ||
| `first_pageview` AggregateFunction(min, DateTime), | ||
| `last_pageview` AggregateFunction(max, DateTime), | ||
| `source` AggregateFunction(argMin, String, DateTime), | ||
| `device` AggregateFunction(argMin, String, DateTime), | ||
| `utm_source` AggregateFunction(argMin, String, DateTime), | ||
| `utm_medium` AggregateFunction(argMin, String, DateTime), | ||
| `utm_campaign` AggregateFunction(argMin, String, DateTime), | ||
| `utm_term` AggregateFunction(argMin, String, DateTime), | ||
| `utm_content` AggregateFunction(argMin, String, DateTime) | ||
|
|
||
| ENGINE "AggregatingMergeTree" | ||
| ENGINE_SORTING_KEY "site_uuid, session_id" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| TOKEN "stats_page" READ | ||
| TOKEN "axis" READ | ||
|
|
||
| NODE _active_visitors_0 | ||
| SQL > | ||
| % | ||
| select | ||
| uniqExact(session_id) as active_visitors | ||
| from _mv_hits | ||
| where | ||
| site_uuid = {{String(site_uuid, 'mock_site_uuid', description="Site UUID", required=True)}} | ||
| and timestamp >= (now() - interval 5 minute) | ||
| {% if defined(post_uuid) %} and post_uuid = {{ String(post_uuid, description="Post UUID to filter on", required=False) }} {% end %} | ||
|
|
||
| TYPE ENDPOINT |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| TOKEN "stats_page" READ | ||
| TOKEN "axis" READ | ||
|
|
||
| NODE timeseries | ||
| SQL > | ||
|
|
||
| % | ||
| {% set _single_day = defined(date_from) and day_diff(date_from, date_to) == 0 %} | ||
| with | ||
| {% if defined(date_from) %} | ||
| toStartOfDay( | ||
| toDate( | ||
| {{ | ||
| Date( | ||
| date_from, | ||
| description="Starting day for filtering a date range", | ||
| required=False, | ||
| ) | ||
| }} | ||
| ) | ||
| ) as start, | ||
| {% else %} toStartOfDay(timestampAdd(today(), interval -7 day)) as start, | ||
| {% end %} | ||
| {% if defined(date_to) %} | ||
| toStartOfDay( | ||
| toDate( | ||
| {{ | ||
| Date( | ||
| date_to, | ||
| description="Finishing day for filtering a date range", | ||
| required=False, | ||
| ) | ||
| }} | ||
| ) | ||
| ) as end | ||
| {% else %} toStartOfDay(today()) as end | ||
| {% end %} | ||
| {% if _single_day %} | ||
| select | ||
| arrayJoin( | ||
| arrayMap( | ||
| x -> toDateTime(toString(toDateTime(x)), {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}), | ||
| range( | ||
| toUInt32(toDateTime(start)), toUInt32(timestampAdd(end, interval 1 day)), 3600 | ||
| ) | ||
| ) | ||
| ) as date | ||
| {% else %} | ||
| select | ||
| arrayJoin( | ||
| arrayMap( | ||
| x -> toDate(x), | ||
| range(toUInt32(start), toUInt32(timestampAdd(end, interval 1 day)), 24 * 3600) | ||
| ) | ||
| ) as date | ||
| {% end %} | ||
|
|
||
|
|
||
| NODE session_data | ||
| DESCRIPTION > | ||
| Read session data from AggregatingMergeTree MV using -Merge combinators | ||
|
|
||
| SQL > | ||
| % | ||
| SELECT | ||
| site_uuid, | ||
| session_id, | ||
| countMerge(pageviews) as pageviews, | ||
| minMerge(first_pageview) as first_pageview, | ||
| maxMerge(last_pageview) as last_pageview | ||
| FROM _mv_session_data_v2 | ||
| WHERE site_uuid = {{ String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True) }} | ||
| GROUP BY site_uuid, session_id | ||
|
|
||
| NODE session_metrics | ||
| DESCRIPTION > | ||
| Calculate session-level metrics (visits, pageviews, bounce rate, avg session duration) | ||
|
|
||
| SQL > | ||
|
|
||
| % | ||
| select | ||
| site_uuid, | ||
| {% if defined(date_from) and day_diff(date_from, date_to) == 0 %} | ||
| toStartOfHour(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) as date, | ||
| {% else %} | ||
| toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) as date, | ||
| {% end %} | ||
| sd.session_id, | ||
| pageviews, | ||
| pageviews = 1 as is_bounce, | ||
| last_pageview - first_pageview as session_sec | ||
| from session_data sd | ||
| inner join filtered_sessions_v2 fs | ||
| on fs.session_id = sd.session_id | ||
|
|
||
|
|
||
| NODE data | ||
| DESCRIPTION > | ||
| Calculate KPIs per time period | ||
|
|
||
| SQL > | ||
|
|
||
| select | ||
| a.date, | ||
| uniq(distinct s.session_id) as visits, | ||
| sum(s.pageviews) as pageviews, | ||
| truncate(avg(s.is_bounce), 2) as bounce_rate, | ||
| truncate(avg(s.session_sec), 2) as avg_session_sec | ||
| from timeseries a | ||
| inner join session_metrics s on a.date = s.date | ||
| group by a.date | ||
| order by a.date | ||
|
|
||
|
|
||
| NODE pathname_pageviews | ||
| DESCRIPTION > | ||
| Calculate pageviews for specific pathname with time granularity handling | ||
|
|
||
| SQL > | ||
|
|
||
| % | ||
| select | ||
| {% if defined(date_from) and day_diff(date_from, date_to) == 0 %} | ||
| toStartOfHour(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) as date, | ||
| {% else %} | ||
| toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) as date, | ||
| {% end %} | ||
| count() pageviews | ||
| from timeseries a | ||
| inner join _mv_hits h on | ||
| {% if defined(date_from) and day_diff(date_from, date_to) == 0 %} | ||
| a.date = toStartOfHour(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) | ||
| {% else %} | ||
| a.date = toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) | ||
| {% end %} | ||
| inner join filtered_sessions_v2 fs | ||
| on fs.session_id = h.session_id | ||
| where | ||
| site_uuid = {{ String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True) }} | ||
| {% if defined(member_status) %} and member_status IN {{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }} {% end %} | ||
| {% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %} | ||
| {% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %} | ||
| {% if defined(post_uuid) %} and post_uuid = {{String(post_uuid, description="Post UUID to filter on", required=False) }} {% end %} | ||
| group by date | ||
| order by date | ||
|
|
||
|
|
||
| NODE finished_data | ||
| SQL > | ||
|
|
||
| % | ||
| select | ||
| a.date as date, | ||
| coalesce(b.visits, 0) as visits, | ||
| {% if defined(pathname) or defined(post_uuid) %}coalesce(c.pageviews, 0){% else %}coalesce(b.pageviews, 0){% end %} as pageviews, | ||
| coalesce(b.bounce_rate, 0) as bounce_rate, | ||
| coalesce(b.avg_session_sec, 0) as avg_session_sec | ||
| from timeseries a | ||
| left join data b on a.date = b.date | ||
| {% if defined(pathname) or defined(post_uuid) %}left join pathname_pageviews c on a.date = c.date{% end %} | ||
| TYPE ENDPOINT |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| TOKEN "stats_page" READ | ||
| TOKEN "axis" READ | ||
|
|
||
| NODE _post_visitor_counts_0 | ||
| SQL > | ||
| % | ||
| select | ||
| post_uuid, | ||
| uniqExact(session_id) as visits | ||
| from _mv_hits | ||
| where | ||
| site_uuid = {{String(site_uuid, 'mock_site_uuid', description="Site UUID", required=True)}} | ||
| and post_uuid IN {{ Array(post_uuids, description="Array of post UUIDs to get visitor counts for", required=True) }} | ||
| group by post_uuid | ||
| order by visits desc | ||
|
|
||
| TYPE ENDPOINT |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,28 @@ | ||||||||||||||||||||||||||||||||
| TOKEN "stats_page" READ | ||||||||||||||||||||||||||||||||
| TOKEN "axis" READ | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| NODE session_data | ||||||||||||||||||||||||||||||||
| SQL > | ||||||||||||||||||||||||||||||||
| % | ||||||||||||||||||||||||||||||||
| SELECT | ||||||||||||||||||||||||||||||||
| site_uuid, | ||||||||||||||||||||||||||||||||
| session_id, | ||||||||||||||||||||||||||||||||
| argMinMerge(device) as device | ||||||||||||||||||||||||||||||||
| FROM _mv_session_data_v2 | ||||||||||||||||||||||||||||||||
| WHERE site_uuid = {{ String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True) }} | ||||||||||||||||||||||||||||||||
| GROUP BY site_uuid, session_id | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| NODE top_devices | ||||||||||||||||||||||||||||||||
| SQL > | ||||||||||||||||||||||||||||||||
| % | ||||||||||||||||||||||||||||||||
| select | ||||||||||||||||||||||||||||||||
| device, | ||||||||||||||||||||||||||||||||
| count() as visits | ||||||||||||||||||||||||||||||||
| from session_data sd | ||||||||||||||||||||||||||||||||
| inner join filtered_sessions_v2 fs | ||||||||||||||||||||||||||||||||
| on fs.session_id = sd.session_id | ||||||||||||||||||||||||||||||||
| group by device | ||||||||||||||||||||||||||||||||
|
Comment on lines
+18
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Include site_uuid in the filtered_sessions_v2 join. Joining only on 🔧 Proposed fix- from session_data sd
- inner join filtered_sessions_v2 fs
- on fs.session_id = sd.session_id
+ from session_data sd
+ inner join filtered_sessions_v2 fs
+ on fs.session_id = sd.session_id
+ and fs.site_uuid = sd.site_uuid📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| order by visits desc | ||||||||||||||||||||||||||||||||
| limit {{ Int32(skip, 0) }},{{ Int32(limit, 50) }} | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| TYPE ENDPOINT | ||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| TOKEN "stats_page" READ | ||
| TOKEN "axis" READ | ||
|
|
||
| NODE _top_locations_0 | ||
| SQL > | ||
|
|
||
| % | ||
| select | ||
| location, | ||
| uniqExact(session_id) as visits | ||
| from _mv_hits h | ||
| inner join filtered_sessions_v2 fs | ||
| on fs.session_id = h.session_id | ||
| where | ||
| site_uuid = {{String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True)}} | ||
| {% if defined(member_status) %} | ||
| and member_status IN ( | ||
| select arrayJoin( | ||
| {{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }} | ||
| || if('paid' IN {{ Array(member_status) }}, ['comped'], []) | ||
| ) | ||
| ) | ||
| {% end %} | ||
| {% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %} | ||
| {% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %} | ||
| {% if defined(post_uuid) %} and post_uuid = {{ String(post_uuid, description="Post UUID to filter on", required=False) }} {% end %} | ||
| group by location | ||
| order by visits desc | ||
| limit {{ Int32(skip, 0) }},{{ Int32(limit, 50) }} | ||
|
|
||
| TYPE ENDPOINT |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| TOKEN "stats_page" READ | ||
| TOKEN "axis" READ | ||
|
|
||
| NODE _top_pages_0 | ||
| SQL > | ||
|
|
||
| % | ||
| select | ||
| case when post_uuid = 'undefined' then '' else post_uuid end as post_uuid, | ||
| pathname, | ||
| uniqExact(session_id) as visits | ||
| from _mv_hits h | ||
| inner join filtered_sessions_v2 fs | ||
| on fs.session_id = h.session_id | ||
| where | ||
| site_uuid = {{String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True)}} | ||
| {% if defined(member_status) %} | ||
| and member_status IN ( | ||
| select arrayJoin( | ||
| {{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }} | ||
| || if('paid' IN {{ Array(member_status) }}, ['comped'], []) | ||
| ) | ||
| ) | ||
| {% end %} | ||
| {% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %} | ||
| {% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %} | ||
| {% if defined(post_uuid) %} and post_uuid = {{ String(post_uuid, description="Post UUID to filter on", required=False) }} {% end %} | ||
| {% if defined(post_type) %} | ||
| {% if post_type == 'post' %} | ||
| and post_type = 'post' | ||
| {% else %} | ||
| and (post_type != 'post' or post_type is null) | ||
| {% end %} | ||
| {% end %} | ||
| group by post_uuid, pathname | ||
| order by visits desc | ||
| limit {{ Int32(skip, 0) }},{{ Int32(limit, 50) }} | ||
|
|
||
| TYPE ENDPOINT |
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.
🧩 Analysis chain
🏁 Script executed:
Repository: qodo-benchmark/Ghost-combined-coderabbit
Length of output: 333
🏁 Script executed:
Repository: qodo-benchmark/Ghost-combined-coderabbit
Length of output: 96
🏁 Script executed:
Repository: qodo-benchmark/Ghost-combined-coderabbit
Length of output: 66
🏁 Script executed:
# Read the Biome configuration cat biome.jsonRepository: qodo-benchmark/Ghost-combined-coderabbit
Length of output: 1859
🏁 Script executed:
Repository: qodo-benchmark/Ghost-combined-coderabbit
Length of output: 66
🌐 Web query:
Biome lint rule noChildrenProp jsx children prop💡 Result:
Biome’s lint rule is
lint/correctness/noChildrenProp(rule name:noChildrenProp). It disallows passingchildrenvia a JSX prop, e.g.<MyComp children={...} />, because the canonical React pattern is to pass children between tags (or as additional args toReact.createElement). It’s recommended and enabled by default, and Biome reports it as an error. [1]What it flags
[1]
What to do instead
[1]
Config (if you want to explicitly set it)
{ "linter": { "rules": { "correctness": { "noChildrenProp": "error" } } } }[1]
If you’re trying to allow function-as-children patterns, note that the upstream ESLint rule (
react/no-children-prop) documents anallowFunctionsoption (Biome may not expose that option the same way). [2]Sources: Biome rule docs [1]; upstream ESLint rule behavior/options [2].
[1] https://biomejs.dev/linter/rules/no-children-prop/
[2] https://help.klocwork.com/2024/en-us/reference/js.react.no.children.prop.htm
Avoid passing
childrenas a prop—Biome lint error.The
noChildrenProprule is enabled by default (via"recommended": trueinbiome.json) and will fail linting. Pass children between tags instead.🔧 Proposed fix
📝 Committable suggestion
🧰 Tools
🪛 Biome (2.3.13)
[error] 90-90: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🤖 Prompt for AI Agents