@@ -28,6 +28,18 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
2828 require Logger
2929
3030 def list_devices ( realm_name , group_name , opts \\ [ ] ) do
31+ keyspace = Realm . keyspace_name ( realm_name )
32+
33+ query =
34+ if opts [ :details ] ,
35+ do: list_device_with_details ( keyspace , group_name , opts ) ,
36+ else: list_grouped_devices ( keyspace , group_name , opts )
37+
38+ query = query |> limit ( opts [ :limit ] )
39+
40+ case Repo . all ( query ) do
41+ end
42+
3143 Xandra.Cluster . run ( :xandra , fn conn ->
3244 query = build_list_devices_statement ( opts )
3345
@@ -54,6 +66,24 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
5466 end )
5567 end
5668
69+ defp list_devices_with_details ( keyspace , group_name , opts ) do
70+ query = list_devices_with_details_query ( keyspace , group_name , opts ) |> limit ( opts [ :limit ] )
71+
72+ case Repo . all ( query ) do
73+ [ ] -> { :error , :group_not_found }
74+ devices -> { :ok , build_device_list ( keyspace , devices , opts ) }
75+ end
76+ end
77+
78+ defp list_grouped_devices ( keyspace , group_name , opts ) do
79+ query = list_grouped_devices_query ( keyspace , group_name , opts )
80+
81+ case Repo . all ( query ) do
82+ [ ] -> { :error , :group_not_found }
83+ devices -> { :ok , build_device_list ( keyspace , devices , opts ) }
84+ end
85+ end
86+
5787 def add_device ( realm_name , group_name , device_changeset ) do
5888 Xandra.Cluster . run ( :xandra , fn conn ->
5989 with { :ok , % { device_id: device_id } } <-
@@ -105,70 +135,57 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
105135 end )
106136 end
107137
108- defp build_list_devices_statement ( opts ) do
109- { select , from , where , suffix } =
110- if opts [ :details ] do
111- select = """
112- SELECT TOKEN(device_id), device_id, aliases, introspection, inhibit_credentials_request,
113- introspection_minor, connected, last_connection, last_disconnection,
114- first_registration, first_credentials_request, last_credentials_request_ip,
115- last_seen_ip, total_received_msgs, total_received_bytes, groups,
116- exchanged_msgs_by_interface, exchanged_bytes_by_interface, old_introspection,
117- attributes
118- """
119-
120- from = """
121- FROM :keyspace.devices
122- """
123-
124- where =
125- if opts [ :from_token ] do
126- """
127- WHERE TOKEN(device_id) > :previous_token
128- AND groups CONTAINS KEY :group_name
129- """
130- else
131- """
132- WHERE groups CONTAINS KEY :group_name
133- """
134- end
135-
136- # TODO: this needs to be done with ALLOW FILTERING, so it's not particularly efficient
137- suffix = """
138- LIMIT :page_size
139- ALLOW FILTERING
140- """
141-
142- { select , from , where , suffix }
143- else
144- select = """
145- SELECT insertion_uuid, device_id
146- """
147-
148- from = """
149- FROM :keyspace.grouped_devices
150- """
151-
152- where =
153- if opts [ :from_token ] do
154- """
155- WHERE group_name = :group_name
156- AND insertion_uuid > :previous_token
157- """
158- else
159- """
160- WHERE group_name = :group_name
161- """
162- end
163-
164- suffix = """
165- LIMIT :page_size
166- """
167-
168- { select , from , where , suffix }
169- end
138+ defp list_devices_with_details_query ( keyspace , group_name , opts ) do
139+ previous_token = opts [ :from_token ]
140+
141+ from_previous_token =
142+ if previous_token ,
143+ do: dynamic ( [ d ] , fragment ( "TOKEN(?)" , d . device_id ) > previous_token ) ,
144+ else: true
145+
146+ # TODO: this needs to be done with ALLOW FILTERING, so it's not particularly efficient
147+ from d in Device ,
148+ prefix: ^ keyspace ,
149+ hints: [ "ALLOW FILTERING" ] ,
150+ select: % {
151+ token: fragment ( "TOKEN(?)" , d . device_id ) ,
152+ device_id: d . device_id ,
153+ aliases: d . aliases ,
154+ introspection: d . introspection ,
155+ inhibit_credentials_request: d . inhibit_credentials_request ,
156+ introspection_minor: d . introspection_minor ,
157+ connected: d . connected ,
158+ last_connection: d . last_connection ,
159+ last_disconnection: d . last_disconnection ,
160+ first_registration: d . first_registration ,
161+ first_credentials_request: d . first_credentials_request ,
162+ last_credentials_request_ip: d . last_credentials_request_ip ,
163+ last_seen_ip: d . last_seen_ip ,
164+ total_received_msgs: d . total_received_msgs ,
165+ total_received_bytes: d . total_received_bytes ,
166+ groups: d . groups ,
167+ exchanged_msgs_by_interface: d . exchanged_msgs_by_interface ,
168+ exchanged_bytes_by_interface: d . exchanged_bytes_by_interface ,
169+ old_introspection: d . old_introspection ,
170+ attributes: d . attributes
171+ } ,
172+ where: ^ from_previous_token ,
173+ where: fragment ( "? CONTAINS KEY ?" , d . groups , ^ group_name )
174+ end
175+
176+ defp list_grouped_devices_query ( keyspace , group_name , opts ) do
177+ previous_token = opts [ :from_token ]
178+
179+ from_previous_token =
180+ if previous_token ,
181+ do: dynamic ( [ d ] , d . insertion_uuid > previous_token ) ,
182+ else: true
170183
171- select <> from <> where <> suffix
184+ from GroupedDevice ,
185+ prefix: ^ keyspace ,
186+ select: [ :insertion_uuid , :device_id ] ,
187+ where: [ group_name: ^ group_name ] ,
188+ where: ^ from_previous_token
172189 end
173190
174191 defp build_device_list ( realm_name , result , opts ) do
@@ -198,6 +215,7 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
198215 defp compute_device_status ( realm_name , device_row ) do
199216 % { "device_id" => device_id } = device_row
200217 device_status = DeviceStatus . from_db_row ( device_row )
218+ # TODO: rebase on newer devicestatus
201219 deletion_in_progress? = deletion_in_progress? ( realm_name , device_id )
202220 % { device_status | deletion_in_progress: deletion_in_progress? }
203221 end
0 commit comments