¿Qué es un valor @TaskLocal y para qué sirve?
Un @TaskLocal es un valor que puede ser atado al contexto de un Task y sirve para pasar información a las "subtareas".
enum Example {
@TaskLocal
// Como variable estática
static var traceID: Int?
}
// Como variable global
@TaskLocal
var contextualNumber: Int = 12
¿Cómo se diferencia del almacenamiento convencional de valores en Swift?
No se puede asignar directamente el valor a un @TaskLocal. En lugar de eso se debe asignar con TaskLocal.withValue(_:operation:file:line:).
El valor solo es válido por la duración del scope del closure.
Example.$traceID.withValue(123) {
print("Dentro de Task: \(Example.traceID ?? -1)")
// Imprime: 123
Task {
print("Task anidada: \(Example.traceID ?? -1)")
// Imprime: 123
}
Task.detached {
print("Task Detached: \(Example.traceID ?? -1)")
// Imprime: -1 (No heredó el valor local)
}
}
¿Qué restricciones existen al declarar y usar un @TaskLocal?
Un @TaskLocal puede ser declarado como una variable estática, o como una variable global usando @TaskLocal desde Swift 6.
¿Qué tipos de tareas heredan los valores locales y cuáles no?
Las Task estructuradas heredan el valor local. Las Task "detached" no lo heredan.
¿En qué situaciones reales tendría sentido usar esta funcionalidad?
Se pueden pasar valores de contexto universal que serían muy tediosos de pasar como parámetros por toda una cadena de llamados y donde el riesgo de que el valor no esté disponible es aceptable. Por ejemplo:
- Contexto de autenticación: Propagar el usuario autenticado a lo largo de una cadena de operaciones asíncronas.
- Configuración de entornos de prueba: Inyectar valores específicos solo durante la ejecución de un test sin modificar código de producción.
- Feature flags temporales: Activar o desactivar comportamientos dentro del alcance de una tarea específica.
Read — Durante la lectura
- ¿Por qué
Task.isCancelledes un ejemplo de valor@TaskLocal?
Se puede implementar como una propiedad estática dentro de una extensión de Task.
extension Task {
@TaskLocal
static var isCancelled: Bool = false
}
- ¿Cómo se declara correctamente un
@TaskLocalpersonalizado?
Con una variable estática o global, marcándola con @TaskLocal.
- ¿Por qué no se puede asignar directamente un valor
@TaskLocalsin usarwithValue()?
withValue garantiza tres cosas:
- El valor solo existe dentro del closure y se restaura automáticamente al salir de él.
- Cada tarea tiene una copia del valor.
El valor no puede modificarse arbitrariamente desde cualquier punto del código, lo que hace el comportamiento predecible.
¿Qué ocurre con el valor dentro de un
Taskestructurado vs. unTask.detached?
En un Task estructurado se hereda el valor a las sub-Task. Como Task.detached no tiene padre, entonces no hereda valores @TaskLocal.
Si en algún punto del código alguien usa Task.detached, el valor desparece silenciosamente sin ningún error de compilador, lo que puede generar bugs difíciles de rastrear.
- ¿Cuánto tiempo permanece vinculado el valor al contexto?
Hasta que se acabe el scope del contexto.
Recite — Después de leer, sin ver el texto
- Explica con tus propias palabras cómo funciona
withValue(_:). // Permite asignar un valor a un@TaskLocaldentro del contexto de una tarea, lo que implica que todas las subtareas van a poder ver ese valor (por copia). Además, funciona como punto de acceso que garantiza inmutabilidad del valor. - ¿Por qué una tarea detached imprime -1 en el ejemplo del artículo? // Task detached no hereda nada porque no tiene contexto. Por eso asumió el valor por defecto:
nily por esto imprimió -1. - ¿Qué alternativa recomienda el autor en lugar de usar
@TaskLocal? // Sugiere inyectar directamente la propiedad
Review — Repaso y reflexión crítica
- ¿Estás de acuerdo con la recomendación del autor de evitar
@TaskLocal? ¿Por qué? // No necesariamente. Aunque en términos generales me gusta ser explícito en la inyección explícita de parámetros, habrá escenarios donde conviene hacer una inyección implícita, como es el caso deisCancelledque necesita ser propagado por todas las subtareas y no se sabe a priori cuántos niveles necesita ser inyectado este valor. - ¿En qué escenario concreto de tu propio desarrollo podrías justificar su uso? // Podría necesitar propagar un valor temporal para hacer una prueba.
- ¿Qué relación existe entre
@TaskLocaly el modelo de concurrencia estructurada de Swift? // La concurrencia estructurada es un modelo donde las tareas forman una jerarquía padre-hijo. Un@TaskLocales una consecuencia directa de esta jerarquía porque puede propagar valores automáticamente hacia abajo en el árbol de tareas.
Top comments (0)