Tareas

Las tareas son acciones que se ejecutan en forma asincrónica, es decir, no esperamos una respuesta inmediata. Esto resulta útil para acciones que pueden tardar algún tiempo en completarse, como una importación de contactos u operaciones sobre grandes listas.

Cuando tenemos una base compuesta por cientos o miles de contactos, administrarlos uno por uno es un trabajo difícil. Para hacerlo más simple existen las tareas: llamadas específicas que resuelven una tarea en particular, por ejemplo unificar dos listas, obtener un muestreo de una lista para testear su calidad o bien eliminar de una lista todos los contactos que hayan marcado alguna campaña como spam.

No es necesario mantener una sesión abierta mientras se estén ejecutando tareas. Podemos cerrar la sesión y volver más tarde para ver los resultados.

Las tareas que podemos utilizar son las siguientes:

  • clean: Limpia una lista, eliminando contactos según el criterio especificado
  • split: Divide una lista en dos
  • duplicate: Duplica una lista
  • substract: Sustrae los contactos presentes en una lista de otra
  • sample: Obtiene un muestreo de los contactos de una lista
  • join: Fusiona dos o más listas en una nueva
  • import: Importación de una nueva lista de contactos

Ya veremos cómo utilizar cada una de esas acciones. Pero antes, veamos cómo utilizar las tareas en general.

Crear tareas

Las tareas salen un poco del esquema REST que todas las otras llamadas utilizan. Para dar comienzo a una tarea se envía un POST a lists, seguido del ID de la lista y el nombre de la acción.

Ya veremos en profundidad cada una de las tareas posibles, pero comencemos con un ejemplo básico. Supongamos entonces que queremos dividir en dos a nuestra lista de ID 123. Deberíamos utilizar la acción split, haciendo un POST a esta URL e indicando con el parámetro numLists la cantidad de porciones en las que la quiero dividir.

https://api.myperfit.com/v2/micuenta/lists/123/split

Veamos el ejemplo completo:

$split = file_get_contents(
    'https://api.myperfit.com/v2/micuenta/lists/123/split',
    false,
    stream_context_create(['http'=> [
        'method'=>'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n".
                    'X-Auth-Token: Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s',
        'content' => http_build_query([
            'numLists' => 2
        ])
    ]])
);
$.ajax({
    type: 'POST',
    url: 'https://api.myperfit.com/v2/micuenta/lists/123/split',
    header: {X-Auth-Token: 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s'}
    data: {
        numLists: 2
    },
    success: function (response) {
        var data = response.data;
    }
});

Detalle de una tarea

Como dijimos, las tareas son asincrónicas: el servidor recibe la órden de ejecutar la tarea y comienza a realizar el proceso de fondo, pero no nos obliga a esperar el resultado del proceso. En cambio, nos entrega un detalle que incluye el ID de la tarea, con el cual podemos identificarla y conocer luego el grado de progreso en el que se encuentra, si ya ha finalizado, si ha ocurrido un error, etc.

La respuesta a nuestro POST anterior, el que dió comienzo a la tarea, tiene un status 202 Accepted y su contenido es similar al siguiente JSON:

{
    "href": "/micuenta/lists/123/split",
    "success": true,
    "task": {
        "id": 556342,
        "type": "LIST_SPLIT",
        "name": "División la lista 123",
        "state": "QUEUED",
        "cancellable": false,
        "message": "En cola",
        "owner": "juanperez",
        "created": "2014-05-20T10:23:04-0300",
        "init": null,
        "end": null,
        "completed": 0,
        "eta": null,
        "request": "/micuenta/lists/123/split",
        "parameters": {
            "numLists": 2
        },
        "result": null
    }
}

En esta respuesta, dento del objeto task, recibimos mucha información sobre la tarea que acabamos de iniciar. Lo más importante es su ID, ya que luego nos permitirá consultar el estado de la tarea, tal como veremos más adelante. Los campos restantes son los siguientes:

Status

Es el estado actual de la tarea. Los valores posibles son los siguientes:

  • QUEUED: la tarea se encuentra en espera, todavía no ha sido iniciada.
  • INITIALIZING: el proceso de la tarea está siendo preparado
  • PROCESSING: la tarea se está procesando
  • COMPLETED: la tarea ha sido completada
  • FAILED: el proceso falló y la tarea no pudo ser completada
  • CANCELLING: tras pedir una cancelación, el proceso está siendo detenido
  • CANCELLED: la tarea ha sido cancelada efectivamente

El camino natural de una tarea es comenzar por estar QUEUED, a la espera de ser iniciada y pasar a INITIALIZING cuando el servidor prepara el entorno para ejecutarla. Luego, la tarea está en progreso y es marcada como PROCESSING. Puede permanecer en ese estado durante un tiempo variable y prolongado en caso de que la tarea sea compleja. Cuando ha finalizado, el estado es COMPLETED.

Si la tarea fue detenida a causa de un error, el estado reportado será FAILED. Por el contrario, si una terea es detenida por pedido del usuario, su estado será CANCELLING y luego CANCELLED. ¡Atención! Como veremos luego, no todas las tareas pueden ser detenidas.

name

El nombre de la tarea, legible para el usuario.

message

Estado de la tarea, legible para el usuario.

cancellable

Indica si se puede cancelar la tarea en el estado actual.

completed

El porcentaje completado de la tarea, indicado de 0 a 1.

type

Indica el tipo de tarea.

eta

Indica el tiempo estimado para que finalice la tarea, en segundos.

created

Fecha de creación de la tarea por parte del usuario.

init

Fecha de inicio de la tarea.

end

Fecha de fin de la tarea.

owner

Muestra el nombre del usuario que generó la tarea.

request

Muestra la url del pedido original.

parameters

Contiene un objeto con los parámetros del pedido que generó la tarea.

result

Contiene un objeto con los resultados de la tarea.

Seguimiento de una tarea

Una vez que generamos una tarea y obtenemos su ID, podemos hacer un seguimiento de su progreso. Esto es muy útil para chequear, cada cierta cantidad de tiempo, si nuestra tarea ha finalizado con éxito.

  • Si estamos programando un script, por ejemplo, podemos activar un cron que chequee el estado de la tarea una vez por minuto.
  • Si estamos programando una interfaz, quizás es buena idea consultar el estado de la tarea con un intervalo más corto, de 20 segundos por ejemplo. Al obtener el porcentaje de progreso y el tiempo estimado de finalización podemos mostrarle al usuario una barra de progreso que se vaya completando y un indicador de cuánto tiempo falta para que la tarea esté lista.

Para chequear el estado de una tarea, debemos hacer un GET a tasks seguido del ID de la tarea en cuestión. Como parametro solamente debemos enviar nuestro token. Por ejemplo:

$task = file_get_contents(
    'https://api.myperfit.com/v2/micuenta/tasks/556342',
    false,
    stream_context_create(['http'=> [
        'method'=>'GET',
        'header' => "X-Auth-Token: $access_token"
    ]])
);
$.ajax({
    type: 'GET',
    url: 'https://api.myperfit.com/v2/micuenta/tasks/556342',
    data: {
        token: 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s'
    },
    success: function (response) {
        var data = response.data;
    }
});

Si el ID es correcto, recibiremos una respuesta 200 OK con un detalle muy similar al que recibimos al crear la tarea, pero con todos los datos actualizados:

{
    "href": "/micuenta/tasks/556342",
    "success": true,
    "data": {
        "id": 556342,
        "type": "LIST_SPLIT",
        "name": "Dividir la lista 123",
        "state": "PROCESSING",
        "cancellable": false,
        "message": "Procesando...",
        "owner": "juanperez",
        "created": "2014-05-20T10:23:04-0300",
        "init": "2014-05-20T10:25:00-0300",
        "end": null,
        "completed": 0.25,
        "eta": 120,
        "request": "/lists/123/split",
        "parameters": {
            "numLists": 2
        },
        "result": null
    }
}

Como podemos observar, el status es ahora PROCESSING, con un 25% de datos procesados tal como indica el campo completed. El campo init nos indica la fecha de inicio del proceso, y en eta encontramos que el tiempo restante es aproximadamente 120 segundos.

Podemos repetir el pedido para chequear el progreso. En cierto momento, cuando la tarea haya finalizado, veremos un detalle como el siguiente:

{
    "href": "/micuenta/tasks/556342",
    "success": true,
    "task": {
        "id": 556342,
        "type": "LIST_SPLIT",
        "name": "Dividir la lista 123",
        "state": "COMPLETED",
        "cancellable": false,
        "message": "Tarea finalizada",
        "owner": "juanperez",
        "created": "2014-05-20T10:23:04-0300",
        "init": "2014-05-20T10:25:00-0300",
        "end": "2014-05-20T10:27:01-0300",
        "completed": 1,
        "eta": 0,
        "request": "/micuenta/lists/123/split",
        "parameters": {
            "numLists": 2
        },
        "result": {
            "contactsProcessed": 645233,
            "newListIds": [150,151,152]
        }
    }
}

Como se puede observar, el campo status figura como COMPLETED y el campo result contiene los resultados de la tarea encargada: como en nuestro ejemplo queríamos divivir una lista en dos, el API nos informará el ID de las listas creadas. Tambien encontramos en end la fecha y hora en que la tarea finalizó efectivamente.

La estructura de parameters y results varía dependiendo de la tarea que se haya iniciado.

Listado de tareas

Si queremos obtener un listado de todas las tareas generadas, podemos hacer un pedido GET a tasks. ¡Atención! De esta forma veremos todas las tareas, tanto las completas como las que estan en curso. Si queremos filtrar el listado podemos hacerlo por state o type.

Por ejemplo, para obtener un listado de las tareas siendo procesadas, podemos hacer:

$tasks = file_get_contents(
    'https://api.myperfit.com/v2/micuenta/tasks?filter[state]=PROCESSING',
    false,
    stream_context_create(['http'=> [
        'method'=>'GET',
        'header' => "X-Auth-Token: $access_token"
    ]])
);
$.ajax({
    type: 'GET',
    url: 'https://api.myperfit.com/v2/micuenta/tasks',
    data: {
        filter: {
            state: 'PROCESSING'
        },
        token: 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s'
    },
    success: function (response) {
        var data = response.data;
    }
});

Recibiremos un status 200 OK con un listado como el siguiente:

{
    "href": "/tasks",
    "success": true,
    "tasks": [
        {
            "id": 111,
            "type": "LIST_CLEAN",
            "name": "Limpieza de lista Clientes",
            "state": "PROCESSING",
            "message": "Procesando...",
            "init": "2014-05-20T10:23:04-0300",
            "owner": "juanperez",
            "completed": 0.1,
            "eta": 160,
            "request": "/micuenta/lists/7849/clean",
            "parameters": {
                "bounced": true
            },
            "result": null
        },
        {
            "id": 112,
            "type": "LIST_IMPORT",
            "name": "Importacion del archivo Lista.XLS",
            "state": "PROCESSING",
            "message": "Procesando...",
            "init": "2014-05-20T10:12:02-0100",
            "owner": "albertogomez",
            "completed": 0.7,
            "eta": 1200,
            "request": "/micuenta/lists/import",
            "parameters": {
                "sourceFile": "Lista.XLS"
            },
            "result": null
        }
    ]
}

Cancelar tareas

A veces es necesario cancelar el proceso de una tarea iniciada. Puede ser porque nos equivocamos en algún parámetro, iniciamos la importanción un archivo erróneo o simplemente nos arrepentimos de haberla encargado. En esos casos, es útil la opción de cancelar la tarea en curso.

No siempre es posible hacerlo: hay acciones que no tienen vuelta atrás una vez iniciadas. Si el campo cancellable indica false, lamentablemente no podemos cancelarla y debemos esperar a que finalice.

Pero si indica true, podemos hacer un POST a tasks seguido del ID de la tarea y la orden cancel, como en este ejemplo:

$task = file_get_contents(
    'https://api.myperfit.com/v2/micuenta/tasks/445/cancel',
    false,
    stream_context_create(['http'=> [
        'method'=>'POST',
        'header' => 'Content-Type: application/x-www-form-urlencoded',
        'content' => http_build_query([
            'token' => 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s'
        ])
    ]])
);
$.ajax({
    type: 'POST',
    url: 'https://api.myperfit.com/v2/micuenta/tasks/445/cancel',
    data: {
        token: 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s'
    },
    success: function (response) {
        var data = response.data;
    }
});

¿Por qué no un DELETE? Porque las tareas nunca se borran, siempre se muestran en el listado. En el caso de cancelarlas, siguen apareciendo, únicamente cambia su status.

{
    "id": 112,
    "type": "LIST_IMPORT",
    "name": "Importacion del archivo Lista.XLS",
    "state": "CANCELLED",
    "message": "Proceso cancelado",
    "init": "2014-05-20T10:12:02-0100",
    "owner": "albertogomez",
    "completed": 0.8,
    "eta": 0,
    "request": "/micuenta/lists/import",
    "parameters": {
        "sourceFile": "Lista.XLS"
    },
    "result": null
}

¡Atención! La tarea sólo puede ser cancelada por el usuario owner o por un usuario con el permiso tasks:cancel habilitado. De lo contrario, se recibirá un error 400 Bad Request.

{
    "href": "/micuenta/tasks/54321",
    "success": false,
    "error": {
        "status": 400,
        "type": "INVALID_OPERATION",
        "userMessage": "No es posible completar la operación solicitada",
    }
}

Tipos de tareas

Limpiar lista

La tarea clean sirve para limpiar los contactos de una lista, según el criterio indicado. Pueden indicarse uno o varios criterios en simultáneo, en cuyo caso los contactos a limpiar serán aquellos que cumplan con alguno de los criterios especificados (no necesariamente con todos ellos). Los contactos seleccionados pueden ser removidos de la lista o eliminados por completo, según se indique.

Como en todas las tareas, hay que especificar en la URL la lista a la cual queremos afectar. Si quisiéramos limpiar todos los contactos, debemos indicar 0 como el número de lista. En todos caso, sólo se limpian los contactos a los que se les haya enviado una campaña para evitar la limpieza de contactos nuevos.

Los parámetros son:

bounced

Si se indica true, limpia los contactos marcados como rebotados.

complained

Se se indica true, limpia los contactos marcados con quejas.

unsubscribed

Si se indica true, limpia los contactos marcados como desuscriptos.

inactiveDays

Si se indica una cifra, limpia los contactos que no demuestran actividad en esa cantidad de días.

quality

Se se indica un número del 0 al 1, limpia los contactos con calidad menor o igual a esa cifra.

action

Indica la acción a realizar sobre los contactos coincidentes con los criterios seleccionados. Puede ser remove para removerlos de la lista, o bien delete para eliminarlos definitivamente.

Veamos un ejemplo con muchos criterios aplicados, donde eliminamos los contactos de la lista 123 que hayan sido marcados como bounced, complained o unsubscribed; cuya calidad sea inferior a 0.1 o bien no hayan tenido actividad en los últimos 180 días:

$clean = file_get_contents(
    'https://api.myperfit.com/v2/lists/123/clean',
    false,
    stream_context_create(['http'=> [
        'method'=>'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n" .
                    'X-Auth-Token: Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s',
        'content' => http_build_query([
            'bounced' => true,
            'complained' => true,
            'unsubscribed' => true,
            'activityDays' => 180,
            'quality' => 0.1,
            'action' => 'delete'
        ])
    ]])
);
$.ajax({
    type: 'POST',
    url: 'https://api.myperfit.com/v2/micuenta/lists/123/clean',
    headers: { X-Auth-Token: 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s' },
    data: {
        bounced: true,
        complained: true,
        unsubscribed: true,
        activityDays: 180,
        quality: 0.1,
        action: 'delete'
    },
    success: function (response) {
        var data = response.data;
    }
});

Dividir lista

La tarea split sirve para dividir una lista en dos o mas partes. Las listas resultantes reciben su nombre a partir del nombre de la lista original: "Nombre Original p01", "Nombre Original p02", etc.

Esta tarea recibe un sólo parámetro:

numLists

Indica la cantidad de listas resultantes. Los contactos se dividen en partes iguales, ajustando el resto en alguna lista si la cantidad de contactos no es exactamente divisible.

Por ejemplo, si queremos dividir la lista 456 en tres partes iguales debemos hacer lo siguiente:

$split = file_get_contents(
    'https://api.myperfit.com/v2/micuenta/lists/456/split',
    false,
    stream_context_create(['http'=> [
        'method'=>'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n" .
                    'X-Auth-Token: Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s',
        'content' => http_build_query([
            'numLists' => 3
        ])
    ]])
);
$.ajax({
    type: 'POST',
    url: 'https://api.myperfit.com/v2/micuenta/lists/456/split',
    headers: { X-Auth-Token: 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s' },
    data: {
        numLists: 3
    },
    success: function (response) {
        var data = response.data;
    }
});

Duplicar lista

La tarea duplicate sirve para crear una copia exacta de una lista.

Toma el siguiente parámetro:

newListName

El nombre de la lista copiada.

Por ejemplo, si queremos duplicar la lista 123 y nombrar a la nueva lista "Copia de Lista A", debemos hacer lo siguiente:

$duplicate = file_get_contents(
    'https://api.myperfit.com/v2/micuenta/lists/123/duplicate',
    false,
    stream_context_create(['http'=> [
        'method'=>'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n" .
                    'X-Auth-Token: Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s',
        'content' => http_build_query([
            'newListName' => 'Copia de Lista A'
        ])
    ]])
);
$.ajax({
    type: 'POST',
    url: 'https://api.myperfit.com/v2/micuenta/lists/123/duplicate',
    headers: { X-Auth-Token: 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s' },    
    data: {
        newListName: 'Copia de lista A'
    },
    success: function (response) {
        var data = response.data;
    }
});

Sustraer listas

La tarea substract sirve para sustraer de una lista todos los contactos presentes otra u otras.

Toma el siguiente parámetro:

excludeListIds

Array de IDs de las listas a excluir.

Por ejemplo, si queremos quitar de la lista 123 todos los contactos que aparezcan en las listas 43, 54 o 12, debemos hacer lo siguiente:

$substract = file_get_contents(
    'https://api.myperfit.com/v2/micuenta/lists/123/substract',
    false,
    stream_context_create(['http'=> [
        'method'=>'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n" .
                    'X-Auth-Token: Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s',
        'content' => http_build_query([
            excludeListIds => [
                43,
                54,
                12
            ]
        ])
    ]])
);
$.ajax({
    type: 'POST',
    url: 'https://api.myperfit.com/v2/micuenta/lists/123/substract',
    headers: { X-Auth-Token: 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s' },    
    data: {
        excludeListIds: [
            43,
            54,
            12
        ]
    },
    success: function (response) {
        var data = response.data;
    }
});

Muestrear lista

La tarea sample sirve para obtener un muestreo de los contactos de una lista. Esto es muy útil para testear la calidad de los contactos de una lista: podemos extraer un muestreo para enviar una campaña y conocer la cantidad de rebotes obtenidos, para extrapolar el resultado a la lista general.

Este pedido recibe dos parámetros:

contactsQty

La cantidad de contactos que debe incluir el muestreo.

newListName

El nombre de la lista de muestreo.

Por ejemplo, para obtener un muestreo de 1000 contactos al azar a partir de la lista 123 debemos hacer lo siguiente:

$sample = file_get_contents(
    'https://api.myperfit.com/v2/micuenta/lists/123/sample',
    false,
    stream_context_create(['http'=> [
        'method'=>'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n" .
                    'X-Auth-Token: Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s',
        'content' => http_build_query([
            'sampleSize' => 1000,
            'newListName' => 'Muestra de Lista A'
        ])
    ]])
);
$.ajax({
    type: 'POST',
    url: 'https://api.myperfit.com/v2/micuenta/lists/123/sample',
    headers: { X-Auth-Token: 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s' },    
    data: {
        sampleSize: 1000,
        newListName: 'Muestra de Lista A'
    },
    success: function (response) {
        var data = response.data;
    }
});

Unificar listas

La tarea join sirve para fusionar dos o más listas en una nueva.

Para ejecutar esta tarea no debemos indicar ID de lista en la URL, pero si debemos enviar los siguientes parámetros:

listIds

Array de IDs de las listas a unir.

newListName

El nombre de la nueva lista generada a partir de la unión de listas.

Por ejemplo, para unir las listas 243, 254 y 212 en una lista llamada "Copia de Lista A" debemos hacer lo siguiente:

$join = file_get_contents(
    'https://api.myperfit.com/v2/micuenta/lists/join',
    false,
    stream_context_create(['http'=> [
        'method'=>'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n" .
                    'X-Auth-Token: Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s',
        'content' => http_build_query([
            'newListName' => 'Copia de Lista A',
            'listIds' => [
                243,
                254,
                212
            ]
        ])
    ]])
);
$.ajax({
    type: 'POST',
    url: 'https://api.myperfit.com/v2/micuenta/lists/join',
    headers: { X-Auth-Token: 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s' },    
    data: {
        newListName: 'Copia de Lista A',
        listIds: [
            243,
            254,
            212
        ]
    },
    success: function (response) {
        var data = response.data;
    }
});