2012-03-12 11 views
12

Tengo un sitio web asp.net-mvc y las personas administran una lista de proyectos. Basado en algún algoritmo, puedo decir si un proyecto está desactualizado. Cuando un usuario inicia sesión, quiero que muestre la cantidad de proyectos obsoletos (similar a cuando veo un número de actualizaciones en la bandeja de entrada).¿Cuál es la forma recomendada de crear una funcionalidad similar a la "Bandeja de entrada" de Stackoverflow?

El algoritmo para calcular proyectos rancio es un poco lento por lo que si cada vez que un usuario se conecta, tengo que:

  1. Ejecutar una consulta para todos los proyectos en los que están al propietario
  2. Ejecutar el IsStale () algoritmo
  3. mostrar el recuento donde IsStale = true

Mi conjetura es que será muy lento. Además, en todo lo que escriba, debería recalcular lo anterior para ver si se ha modificado.

Otra idea que tuve fue crear una tabla y ejecutar un trabajo de todo minutos para calcular proyectos obsoletos y almacenar el recuento más reciente en esta tabla de métricas. Luego solo pregunta eso cuando los usuarios inicien sesión. El problema es que todavía tengo que mantener esa tabla sincronizada y si solo se recalcula una vez por minuto, si las personas actualizan proyectos, no cambiará el valor hasta después de un minuto.

¿Alguna idea de una forma rápida y escalable de admitir este concepto de bandeja de entrada para alertar a los usuarios sobre la cantidad de elementos a revisar?

Respuesta

10

El primer paso es siempre un análisis adecuado requisito. Supongamos que soy un Gerente de proyecto. Me conecto al sistema y muestra mi único proyecto como a tiempo. Un desarrollador viene a mi oficina y me dice que hay un retraso en su actividad. Selecciono la actividad del desarrollador y cambio su duración. El sistema sigue mostrando mi proyecto como a tiempo, así que felizmente dejar el trabajo.

¿Cómo crees que me sentiría si recibo una llamada telefónica a las 3:00 AM del cliente pidiéndome una explicación de por qué el proyecto ya no es a tiempo? Obviamente, bastante sorprendido, porque el sistema no me advirtió de ninguna manera. ¿Por qué sucedió eso? Porque tuve que esperar 30 segundos (¿por qué no solo 1 segundo?) Para la próxima ejecución de un trabajo programado para actualizar el estado del proyecto.

Eso no puede ser una solución. Se debe enviar una advertencia de inmediato al usuario, incluso si lleva 30 segundos ejecutar el proceso IsStale(). Muestre al usuario una imagen loading... o cualquier otra cosa, pero asegúrese de que el usuario tenga datos precisos.

Ahora, en cuanto a la aplicación, nada se puede hacer para huir de la emisión anterior: tendrá que ejecutar ese proceso cuando algo que afecta a algunos cambios de fechas de vencimiento. Sin embargo, lo que puede hacer es ejecutar innecesariamente ese proceso. Por ejemplo, mencionó que podría ejecutarlo siempre que el usuario inicie sesión. ¿Qué sucede si 2 o más usuarios inician sesión y ven el mismo proyecto y no cambian nada? No sería necesario ejecutar el proceso dos veces.

Whatsmore, si se asegura que el proceso se ejecuta cuando el usuario actualiza el proyecto, no será necesario para ejecutar el proceso en cualquier otro momento.En conclusión, este esquema tiene las siguientes ventajas y desventajas en comparación con la solución de "sondeo":

Ventajas

  • Sin trabajo programado
  • No se ejecuta el proceso que no sean necesarios (esto es discutible, ya que podría establecer una bandera dirty en el proyecto y sólo se ejecutan si está true)
  • No hay consultas innecesarias del valor dirty
  • El usuario siempre estará informado de la situación actual y real del proyecto (que es, con mucho, el elemento más importante a tratar en cualquier solución dada)

Desventajas

  • Si una el usuario actualiza un proyecto y luego lo vuelve a cerrar en cuestión de segundos, el proceso se ejecutará dos veces (en el esquema de sondeo, el proceso podría no ejecutarse una vez en ese período, según la frecuencia que se programó)
  • El usuario que actualiza el proyecto deberá esperar a que el proceso finalice

Cambiando a cómo implementa el sistema de notificación de una manera similar a StackOverflow, esa es una pregunta bastante diferente. Supongo que tienes una relación de muchos a muchos con usuarios y proyectos. La solución más simple sería la adición de un solo atributo de la relación entre esas entidades (la media tabla ):

Cardinalidades: Un usuario tiene muchos proyectos. Un proyecto tiene muchos usuarios

De esta forma, cuando ejecuta el proceso, debe actualizar el Has_pending_notifications de cada usuario con el nuevo resultado. Por ejemplo, si un usuario actualiza un proyecto y ya no es a tiempo, debe establecer en true el campo todos los usuarios Has_pending_notifications para que se den cuenta de la situación. De manera similar, configúrelo en false cuando el proyecto sea a tiempo (entiendo que solo desea asegurarse de que las notificaciones se muestren cuando el proyecto ya no esté a tiempo).

Tomando el ejemplo de StackOverflow, cuando un usuario lee una notificación, debe establecer la bandera en false. Asegúrese de no utilizar marcas de tiempo para adivinar si un usuario ha leído una notificación: iniciando sesión no significa leyendo las notificaciones.

Por último, si la notificación en sí es bastante compleja, puede alejarlo de la relación entre los usuarios y los proyectos e ir a por algo como esto:

Cardinalidades: Un usuario tiene muchos proyectos . Un proyecto tiene muchos usuarios. Un usuario tiene muchas notificaciones. Una notificación tiene un usuario. Un proyecto tiene muchas notificaciones.Una notificación tiene un proyecto.

espero que algo de lo que he dicho ha tenido sentido, o darle alguna otra idea mejor :)

3

Haga un campo "añejo". Ejecuta una instrucción SQL que actualiza stale = 1 con todos los registros donde stale = 0 AND (ese algoritmo devuelve true). A continuación, ejecute una instrucción SQL que seleccione todos los registros donde añejo = 1.

La razón por la que esto funciona rápido es porque los analizadores SQL, como PHP, no deberían hacer la segunda mitad de la instrucción AND si la primera mitad devuelve verdadera, haciendo que sea muy rápida en toda la lista, verificando todas las registros, tratando de hacerlos añejos SI NO ya estancados. Si ya está obsoleto, el algoritmo no se ejecutará, lo que le ahorrará tiempo. Si no es así, el algoritmo se ejecutará para ver si se ha quedado obsoleto y, luego, obsoleto se establecerá en 1.

La segunda consulta simplemente devuelve todos los registros obsoletos donde está obsoleto = 1.

0

Usted puede hacer esto:

En la base de datos cambiar la marca de tiempo cada vez que un proyecto se accede por el usuario. Cuando el usuario inicia sesión, extrae todos sus proyectos. Verifique la marca de tiempo y compárela con la fecha de hoy; si es anterior a n días, agréguela a la lista obsoleta. No creo que la comparación de fechas dé como resultado una lógica lenta.

+0

su método IsStale() que es lento – leora

+1

Tiempo comparación sello no debe ser lento, pero su otra opción es añadir esta lógica en el lado de la base de datos. Si puede, cree un procedimiento almacenado que haga la comparación y devuelva el resultado como una columna adicional. – evasilchenko

+0

IsStale() NO es solo una comparación de marca de tiempo.es un algoritmo más complicado para ver si los datos están desactualizados en función de una serie de factores – leora

6

Se puede hacer de la siguiente manera:

  1. Para cada registro de usuarios Agregar un campo de fecha y hora sayng la última vez que se realiza el cálculo lenta. Llámelo LastDate.
  2. Para cada proyecto, agregue un valor booleano para indicar si debe aparecer en la lista.Llamarlo: Seleccionado
  3. Cuando se ejecuta el procedimiento lento establece que actualice los seleccionados campos campos
  4. Ahora, cuando el usuario inicia sesión si LastDate está lo suficientemente cerca ahora utiliza los resultados del último cómputo lento y simplemente tome todo el proyecto con Seleccionado true. De lo contrario, no volverá a la computación lenta. El procedimiento anterior es óptima, becuase que re-calcular el procedimiento lento únicamente si son realmente necesarias, mientras que la ejecución de un procedimiento a intervalos fijos de tiempo ... tiene el riesgo de perder el tiempo porque tal vez el usuario neber utilizar el resultado de un cálculo .
0

creo que las cuestiones fundamentales deben ser resueltos antes de pensar en bases de datos y código. El principal de estos es: "¿Por qué IsStale() es lento?"

Según otros comentarios, está claro que el concepto de que esto es lento no es negociable. ¿Este cálculo está fuera de tus manos? ¿Los resultados son resistentes al almacenamiento en caché? ¿Qué nivel de cambio desencadena la recalculación?

haber escrito los sistemas de programación en el pasado, hay dos tipos de cambios: los que puede pasar dentro de la holgura y aquellos que provocar una cascada de cambios de horario. Del mismo modo, hay dos tipos de reconstrucciones: total y local. Las reconstrucciones totales son obvias; las reconstrucciones locales intentan minimizar el "daño" a otros recursos programados.

Aquí está el quid de la cuestión: si tiene una reconstrucción total en cada actualización, podría estar buscando retrasos de 30 minutos desde el momento del cambio hasta el horario estable. (Estoy basando esto en mi experiencia con el tiempo de reconstrucción de un sistema ERP con una carga de trabajo muy compleja).

Si la realidad de su sistema es que este tipo de tareas en unos 30 minutos, con un objetivo de diseño de la gratificación instantánea para sus usuarios es contraria a la realidad del terreno de la cuestión. Sin embargo, es posible que detecte inconsistencias de programación mucho más rápido que la reconstrucción. En ese caso, podría mostrarle al usuario "el horario se ha desbordado, volver a calcular los últimos tiempos" o algo similar ... pero sospecho que si tiene muchos cambios en el cronograma ingresados ​​por diferentes usuarios al mismo tiempo, el sistema se degradaría en una visualización continua de ese aviso. Sin embargo, al menos tiene la ventaja de que puede realizar cambios en lotes durante un período de tiempo para la próxima reconstrucción.

Es por esta razón que la mayoría de los problemas de programación que he visto en realidad no hacen recálculos en tiempo real. En el contexto de la situación de ERP hay un maestro de programación que es responsable de la programación del taller y cualquier cambio se canaliza a través de ellos. El cronograma "maestro" se regeneró antes de cada turno (los turnos fueron 12 horas, por lo tanto, dos veces al día) y durante el turno se trabajaron en modificaciones "locales" que no mezclaron el cronograma maestro hasta el próximo bloque de 12 horas.

En una situación mucho más simple (diseño de software) el programa se actualiza una vez al día en respuesta a los informes de progreso del día. Se recibieron malas noticias durante el scrum de la mañana siguiente, junto con el calendario actualizado.

Hacer una larga historia corta, estoy pensando que tal vez este es un momento "unask la cuestión", en el supuesto necesita ser cuestionado. Si la recalculación es lo suficientemente grande como para que las actualizaciones continuas no sean prácticas, entonces es necesario alinear las expectativas con la realidad. O el algoritmo necesita trabajo (optimización para cambios locales), la granja de hardware necesita expansión o el tiempo de las expectativas de "verdad" necesita ser recalibrado.

Una respuesta más refinada sería francamente requerir más detalles que "sólo asumir un proceso costoso" debido a que los puntos adecuados de ataque a ese proceso son imposibles de conocer.

Cuestiones relacionadas