Creando tu propio registro de actividad en GAE / P

Me gustaría registrar la actividad del usuario en mi aplicación para presentarla a los usuarios y también con fines administrativos. Mis clientes son empresas, por lo que hay tres niveles en los que puedo presentar la actividad:

  1. Actividad de un solo usuario.
  2. Actividad de todos los usuarios de una empresa.
  3. Toda la actividad

Para hacer el registro, crearía un modelo para almacenar las entradas del registro. Veo algunas formas de hacer esto.

Primero, podría almacenar cada actividad registrada en su propia entidad y luego consultar según sea necesario:

class Activity(ndb.Model): activity = ndb.StringProperty() user_id = ndb.StringProperty() company_id = ndb.StringProperty() 

En segundo lugar, podría almacenar toda la actividad de un usuario en una sola entidad:

 class UserActivity(ndb.Model): activity = ndb.StringProperty(repeated=True) # Note this is now a list company_id = ndb.StringProperty() 

Tercero, podría almacenar toda la actividad de una empresa en una sola entidad:

 class CompanyActivity(ndb.Model): activity = ndb.StringProperty(repeated=True) # Would store user_id here somehow 

¿Cuáles son las compensaciones de funcionalidad / rendimiento en las tres opciones? Entiendo que hay posibles problemas de contención con la segunda y tercera opciones si hay transacciones frecuentes de venta, pero supongamos que no es un problema por el bien de la discusión.

Para la segunda y tercera opciones, ¿existen ventajas significativas en la reducción del número total de entidades del almacén de datos (ya que se consolidarían en menos entidades)? ¿O debería simplemente ir con la primera opción?

La única ventaja de usar la propiedad repetida sería que evitaría el eventual problema de coherencia: cada vez que lea una entidad UserActivity o CompanyActivity , sabrá que obtiene la lista completa de todas las actividades. Cuando utilice el primer enfoque, tendrá que realizar una consulta para obtener dicha lista y la lista puede perder actividades muy recientes, ya que es posible que el índice de consulta respectivo aún no se haya actualizado para reflejarlas.

Pero, además del problema potencial de contención que mencionó, hay otra desventaja a considerar para el enfoque de propiedad repetida: el tamaño de estas entidades boostá gradualmente a medida que se agreguen más y más actividades a la lista, lo que se traduce en:

  • progresivamente más lento get() / put() veces, por lo que deteriora gradualmente el rendimiento general de la aplicación
  • el riesgo de alcanzar el tamaño máximo de la entidad del almacén de datos (~ 1 MB, consulte Límites ), lo que requeriría una lógica adicional para dividir la lista en varias entidades

El tercer enfoque en particular también requerirá un método menos trivial para obtener informes de actividad por usuario.

Me quedo con el primer enfoque, es el enfoque más flexible y escalable y las desventajas son menores:

  • El eventual problema de consistencia es que, en mi humilde opinión, no es un factor decisivo (y podría haber formas de reducir su impacto)
  • El espacio de almacenamiento adicional (para las propiedades de ID de usuario / empresa almacenadas en cada entidad de Activity más índices más grandes debido al mayor número de entidades) es MUY válido (el almacenamiento es barato).

También sugeriría el primer enfoque pero con KeyProperty :

 class Activity(ndb.Model): activity = ndb.StringProperty() user_id = ndb.KeyProperty(kind='User') company_id = ndb.KeyProperty(kind='Company') 

El código sería mucho más limpio desde el principio y siempre se puede ajustar más tarde.

Por lo demás, Dan ha cubierto muy bien los puntos más importantes.