Подписка на мероприятия AWS AppSync в зависимости от местоположения

Я понимаю, как выполнять геопространственные запросы через AppSync для поиска событий в диапазоне расстояний от координаты GPS, подключив преобразователь, связанный с ElasticSesarch, как описано здесь.

Однако что, если я хочу, чтобы мой клиент подписался на новые события, создаваемые в пределах этого диапазона расстояний?

  1. пользователь подписывается на местоположение
  2. если рядом с этим местом создается событие, уведомить пользователя

Я знаю, что могу прикрепить преобразователь к типам подписок, но похоже, что он заставляет вас предоставлять источник данных, когда я просто хочу фильтровать подписки, проверяя расстояние между координатами GPS.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
985
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это отличный вопрос, и я думаю, что есть несколько способов его решить. Сложность здесь в том, что вам нужно придумать способ задать вопрос «Какие подписки заинтересованы в мероприятии в этом месте». Вот один из возможных путей вперед.

Следующее предполагает эти части схемы:

// Whatever custom object has a location 
type Post {
  id: ID!
  title: String
  location: Location
}
input PublishPostInput {
  id: ID!
  title: String
  location: Location
  subscriptionID: ID
}
type PublishPostOutput {
  id: ID!
  title: String
  location: Location
  subscriptionID: ID
}

type Location {
  lat: Float,
  lon: Float
}
input LocationInput {
  lat: Float,
  lon: Float
}

# A custom type to hold custom tracked subscription information
# for location discover
type OpenSubscription {
  subscriptionID: ID!
  location: Location
  timestamp: String!
}
type OpenSubscriptionConnection {
  items: [OpenSubscription]
  nextToken: String
}

type Query {
  # Query elasticsearch index for relevant subscriptions
  openSubscriptionsNear(location: LocationInput, distance: String): OpenSubscriptionConnection
}
type Mutation {
  # This mutation uses a local resolver (e.g. a resolver with a None data source) and simply returns the input as is.
  publishPostToSubscription(input: PublishPostInput): PublishPostOutput
}
type Subscription {
  # Anytime someone passes an object with the same subscriptionID to the "publishPostToSubscription" mutation field, get updated.
  listenToSubscription(subscriptionID: ID!): PublishPostOutput
    @aws_subscribe(mutations:["publishPostToSubscription"])
}

Предполагая, что вы используете DynamoDB в качестве основного источника истины, настройте поток DynamoDB, который вызывает лямбда-функцию PublishIfInRange. Эта функция PublishIfInRange будет выглядеть примерно так

// event - { location: { lat, lon }, id, title, ... }
function lambdaHandler(event) {

  const relevantSubscriptions = await callGraphql(`
    query GetSubscriptions($location: LocationInput) {
      openSubscriptionsNear(location:$location, distance: "10 miles") {
        subscriptionID
      }
    }
  `, { variables: { location: event.location }})

  for (const subscription of relevantSubscriptions) {
    callGraphql(`
      mutation PublishToSubscription($subID: ID!, $obj: PublishPostInput) {
        publishPostToSubscription(input: $obj) {
          id
          title
          location { lat lon }
          subscriptionID
        }
      }
    `, { variables: { input: { ...subscription, ...event }}})
  }
}

Вам нужно будет вести реестр подписок, индексированных по местоположению. Один из способов сделать это - заставить ваше клиентское приложение вызывать мутацию, которая создает объект подписки с местоположением и идентификатором подписки (например, mutation { makeSubscription(loc: $loc) { ... } }, если вы используете $ util.autoId () для генерации идентификатора подписки в преобразователе). После того, как у вас есть идентификатор подписки, вы можете выполнить вызов подписки через graphql и передать идентификатор подписки в качестве аргумента (например, subscription { listenToSubscription(subscriptionID: "my-id") { id title location { lat lon } } }). Когда вы делаете этот вызов подписки выше, AppSync создает тему и разрешает текущему пользователю подписаться на эту тему. Тема уникальна для вызываемого поля подписки и набора аргументов, передаваемых в поле подписки. Другими словами, тема получает только объекты

Теперь всякий раз, когда создается объект, запись передается в лямбда-функцию через потоки DynamoDB. Лямбда-функция запрашивает у elasticsearch все открытые подписки рядом с этим объектом, а затем публикует запись для каждой из этих открытых подписок.

Я считаю, что это должно продвинуть вас достаточно далеко, но если у вас миллионы пользователей в ограниченном пространстве, вы, вероятно, столкнетесь с проблемами масштабирования. Надеюсь это поможет

Чтобы масштабировать это, вы можете лучше понять, как разделить subscriptionID. Например, вы можете разбить свою карту на N небольших фрагментов, а затем на вашем клиенте попросить их подписаться на Y ближайших фрагментов в сетке и выполнить любую мелкую фильтрацию на клиенте. Таким образом, у вас будет не более N идентификаторов подписки, поэтому процесс разветвления будет намного меньше, чем если бы у каждого пользователя была собственная подписка.

mparis 13.07.2018 02:39

Учитывая проблему масштабирования и стоимость обслуживания многих каналов подписки со стороны пользователя, не будет ли разумнее просто запрашивать чаще, чтобы убедиться, что пользователь обновляется почти в реальном времени?

AJ Z. 13.07.2018 03:22

Опрос - гораздо более простой и экономичный вариант, если истинный режим реального времени не является обязательным требованием.

mparis 13.07.2018 03:24

Другие вопросы по теме