Skip to content

Commit

Permalink
Edit AppEngine api :use keyspace name instead of realm in queries
Browse files Browse the repository at this point in the history
Currently Astarte instances are not allowd to share the same database due to a conflict in namespaces
resolution (eg. two realms with same name in different astarte instances now share the same kespace,
that's not good)

This commit introduce univoque mapping between the pair <Astarte instance id, realm name>
and keyspace name (see also  astarte-platform/astarte_core#105), this way even
with the same name, realms do not share the same keyspace.
Also, the env var `ASTARTE_INSTANCE_ID`, defaulting to `""` has been added to
maintain backward compatibility.

Trivially change all queries to the database to reflect this change, both in `lib` and `tests`.

Signed-off-by: Eddy Babetto <eddy.babetto@secomind.com>
  • Loading branch information
eddbbt committed Apr 24, 2024
1 parent 34be0c1 commit 71fcd47
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,7 @@ defmodule Astarte.AppEngine.API.Config do
defdelegate cqex_nodes!, to: DataAccessConfig

defdelegate xandra_options!, to: DataAccessConfig

defdelegate astarte_instance_id!, to: DataAccessConfig
defdelegate astarte_instance_id, to: DataAccessConfig
end
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ defmodule Astarte.AppEngine.API.Device do
alias Astarte.DataAccess.Device, as: DeviceQueries
alias Astarte.DataAccess.Interface, as: InterfaceQueries
alias Ecto.Changeset
alias Astarte.Core.CQLUtils
require Logger

def list_devices!(realm_name, params) do
Expand Down Expand Up @@ -412,7 +413,10 @@ defmodule Astarte.AppEngine.API.Device do
|> DateTime.to_unix(:microsecond)

with {:ok, mappings} <-
Mappings.fetch_interface_mappings(realm_name, interface_descriptor.interface_id),
Mappings.fetch_interface_mappings(
realm_name,
interface_descriptor.interface_id
),
{:ok, endpoint} <-
resolve_object_aggregation_path(path, interface_descriptor, mappings),
endpoint_id <- endpoint.endpoint_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
alias Astarte.AppEngine.API.Groups.Group
alias Astarte.AppEngine.API.Device.DeviceStatus
alias Astarte.AppEngine.API.Device.DevicesList
alias Astarte.Core.CQLUtils
alias Astarte.AppEngine.API.Config
alias Astarte.Core.Device
alias Astarte.Core.Realm

Expand Down Expand Up @@ -53,7 +55,7 @@ defmodule Astarte.AppEngine.API.Groups.Queries do

def list_groups(realm_name) do
Xandra.Cluster.run(:xandra, fn conn ->
query = "SELECT DISTINCT group_name FROM :realm.grouped_devices"
query = "SELECT DISTINCT group_name FROM :keyspace.grouped_devices"

with {:ok, prepared} <- prepare_with_realm(conn, realm_name, query),
{:ok, %Xandra.Page{} = page} <- Xandra.execute(conn, prepared) do
Expand All @@ -70,7 +72,7 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
Xandra.Cluster.run(:xandra, fn conn ->
query = """
SELECT DISTINCT group_name
FROM :realm.grouped_devices
FROM :keyspace.grouped_devices
WHERE group_name = :group_name
"""

Expand Down Expand Up @@ -181,7 +183,7 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
"""

from = """
FROM :realm.devices
FROM :keyspace.devices
"""

where =
Expand Down Expand Up @@ -209,7 +211,7 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
"""

from = """
FROM :realm.grouped_devices
FROM :keyspace.grouped_devices
"""

where =
Expand Down Expand Up @@ -270,7 +272,7 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
# TODO change this once NoaccOS' PR is in
deletion_in_progress_stmt = """
SELECT *
FROM :realm.deletion_in_progress
FROM :keyspace.deletion_in_progress
WHERE device_id=:device_id
"""

Expand Down Expand Up @@ -326,7 +328,7 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
end

defp device_exists?(conn, realm_name, encoded_device_id) do
query = "SELECT device_id FROM :realm.devices WHERE device_id = :device_id"
query = "SELECT device_id FROM :keyspace.devices WHERE device_id = :device_id"

with {:ok, device_id} <- Device.decode_device_id(encoded_device_id),
{:ok, prepared} <- prepare_with_realm(conn, realm_name, query),
Expand All @@ -345,7 +347,7 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
end

defp group_exists?(conn, realm_name, group_name) do
query = "SELECT group_name FROM :realm.grouped_devices WHERE group_name = :group_name"
query = "SELECT group_name FROM :keyspace.grouped_devices WHERE group_name = :group_name"

with {:ok, prepared} <- prepare_with_realm(conn, realm_name, query),
{:ok, %Xandra.Page{} = page} <-
Expand All @@ -365,7 +367,7 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
defp do_check_device_in_group(conn, realm_name, group_name, encoded_device_id) do
query = """
SELECT groups
FROM :realm.devices
FROM :keyspace.devices
WHERE device_id = :device_id
"""

Expand Down Expand Up @@ -395,13 +397,13 @@ defmodule Astarte.AppEngine.API.Groups.Queries do

defp remove_from_group(conn, realm_name, group_name, encoded_device_id) do
device_query = """
UPDATE :realm.devices
UPDATE :keyspace.devices
SET groups = groups - :group_name_set
WHERE device_id = :device_id
"""

grouped_devices_query = """
DELETE FROM :realm.grouped_devices
DELETE FROM :keyspace.grouped_devices
WHERE group_name = :group_name
AND insertion_uuid = :insertion_uuid
AND device_id = :device_id
Expand Down Expand Up @@ -442,7 +444,7 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
defp retrieve_group_insertion_uuid(conn, realm_name, group_name, device_id) do
query = """
SELECT groups
FROM :realm.devices
FROM :keyspace.devices
WHERE device_id = :device_id
"""

Expand All @@ -469,13 +471,13 @@ defmodule Astarte.AppEngine.API.Groups.Queries do

defp add_to_group(conn, realm_name, group_name, devices) do
device_query = """
UPDATE :realm.devices
UPDATE :keyspace.devices
SET groups = groups + :group_map
WHERE device_id = :device_id
"""

grouped_devices_query = """
INSERT INTO :realm.grouped_devices
INSERT INTO :keyspace.grouped_devices
(group_name, insertion_uuid, device_id)
VALUES
(:group_name, :insertion_uuid, :device_id)
Expand Down Expand Up @@ -523,9 +525,12 @@ defmodule Astarte.AppEngine.API.Groups.Queries do
end

defp prepare_with_realm(conn, realm_name, query) do
keyspace_name =
CQLUtils.realm_name_to_keyspace_name(realm_name, Config.astarte_instance_id!())

with {:valid, true} <- {:valid, Realm.valid_name?(realm_name)},
query_with_realm = String.replace(query, ":realm", realm_name),
{:ok, prepared} <- Xandra.prepare(conn, query_with_realm) do
query_with_keyspace = String.replace(query, ":keyspace", keyspace_name),
{:ok, prepared} <- Xandra.prepare(conn, query_with_keyspace) do
{:ok, prepared}
else
{:valid, false} ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
defmodule Astarte.AppEngine.API.Queries do
alias CQEx.Query, as: DatabaseQuery
alias CQEx.Result, as: DatabaseResult
alias Astarte.AppEngine.API.Config
alias Astarte.Core.CQLUtils

require Logger

Expand All @@ -44,15 +46,15 @@ defmodule Astarte.AppEngine.API.Queries do
def check_astarte_health(client, consistency) do
schema_statement = """
SELECT count(value)
FROM astarte.kv_store
FROM #{CQLUtils.realm_name_to_keyspace_name("astarte", Config.astarte_instance_id!())}.kv_store
WHERE group='astarte' AND key='schema_version'
"""

# no-op, just to check if nodes respond
# no realm name can contain '_', '^'
realms_statement = """
SELECT *
FROM astarte.realms
FROM #{CQLUtils.realm_name_to_keyspace_name("astarte", Config.astarte_instance_id!())}.realms
WHERE realm_name='_invalid^name_'
"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ defmodule Astarte.AppEngine.API.Rooms.Room do
alias Astarte.AppEngine.API.RPC.DataUpdaterPlant
alias Astarte.AppEngine.API.RPC.DataUpdaterPlant.VolatileTrigger
alias Astarte.AppEngine.API.Utils
alias Astarte.AppEngine.API.Config
alias Astarte.AppEngine.APIWeb.Endpoint
alias Astarte.Core.Triggers.SimpleTriggerConfig
alias Astarte.Core.Triggers.SimpleTriggersProtobuf.AMQPTriggerTarget
Expand All @@ -35,7 +34,6 @@ defmodule Astarte.AppEngine.API.Rooms.Room do
alias Astarte.Core.Device
alias Astarte.DataAccess.Database
alias Astarte.AppEngine.API.Rooms.Queries

require Logger

# API
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
defmodule Astarte.AppEngine.API.Stats.Queries do
alias Astarte.Core.Realm
alias Astarte.AppEngine.API.Stats.DevicesStats

alias Astarte.Core.CQLUtils
alias Astarte.AppEngine.API.Config
require Logger

def get_devices_stats(realm) do
Expand All @@ -43,7 +44,7 @@ defmodule Astarte.AppEngine.API.Stats.Queries do
defp get_total_devices_count(conn, realm) do
query = """
SELECT count(device_id)
FROM :realm.devices
FROM :keyspace.devices
"""

with {:ok, prepared} <- prepare_with_realm(conn, realm, query),
Expand All @@ -58,7 +59,7 @@ defmodule Astarte.AppEngine.API.Stats.Queries do
# TODO: we should do this via DataUpdaterPlant instead of using ALLOW FILTERING
query = """
SELECT count(device_id)
FROM :realm.devices
FROM :keyspace.devices
WHERE connected=true
ALLOW FILTERING
"""
Expand All @@ -74,9 +75,12 @@ defmodule Astarte.AppEngine.API.Stats.Queries do
# TODO: copypasted from Groups.Queries, this is going to be moved to Astarte.DataAccess
# when we move everything to Xandra
defp prepare_with_realm(conn, realm_name, query) do
keyspace_name =
CQLUtils.realm_name_to_keyspace_name(realm_name, Config.astarte_instance_id!())

with {:valid, true} <- {:valid, Realm.valid_name?(realm_name)},
query_with_realm = String.replace(query, ":realm", realm_name),
{:ok, prepared} <- Xandra.prepare(conn, query_with_realm) do
query_with_keyspace = String.replace(query, ":keyspace", keyspace_name),
{:ok, prepared} <- Xandra.prepare(conn, query_with_keyspace) do
{:ok, prepared}
else
{:valid, false} ->
Expand Down
Loading

0 comments on commit 71fcd47

Please sign in to comment.