{"id":4852,"date":"2018-03-19T11:50:44","date_gmt":"2018-03-19T18:50:44","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=4852"},"modified":"2025-06-13T21:20:32","modified_gmt":"2025-06-14T04:20:32","slug":"timed-tasks-using-couchbase-go","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/timed-tasks-using-couchbase-go\/","title":{"rendered":"Tareas cronometradas con Couchbase y Go"},"content":{"rendered":"<h5>Alberto Marchetti es desarrollador full-stack y autor de<a href=\"https:\/\/hydex11.net\/renderscript_parallel_computing_on_android_the_easy_way\" target=\"_blank\" rel=\"noopener noreferrer\">\u00a0\"<\/a><a href=\"https:\/\/hydex11.net\/renderscript_parallel_computing_on_android_the_easy_way\" target=\"_blank\" rel=\"noopener noreferrer\">RenderScript: computaci\u00f3n paralela en Android, de forma sencilla<\/a>.\" Vive siempre al l\u00edmite, lanz\u00e1ndose constantemente al descubrimiento de lenguas y tecnolog\u00edas modernas.<\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignleft wp-image-4851\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/03\/photo5834550288516754817-1024x1024.jpg\" alt=\"\" width=\"396\" height=\"396\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-1024x1024.jpg 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-300x300.jpg 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-150x150.jpg 150w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-768x768.jpg 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-65x65.jpg 65w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-50x50.jpg 50w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-20x20.jpg 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817.jpg 1280w\" sizes=\"auto, (max-width: 396px) 100vw, 396px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h2>Tareas cronometradas<strong>\u00a0utilizando Couchbase y Go<\/strong><\/h2>\n<p>En este post voy a mostrar c\u00f3mo puedes explotar el sistema de indexaci\u00f3n de Couchbase para crear un sistema distribuido de tareas cronometradas. El c\u00f3digo de ejemplo para el proyecto, junto con sus instrucciones de ejecuci\u00f3n, se puede encontrar en <a href=\"https:\/\/github.com\/cmaster11\/cb-blog-timed-tasks\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/github.com\/cmaster11\/cb-blog-timed-tasks<\/a>.<br \/>\n<em>Descargo de responsabilidad: Debido a la complejidad del tema, en esta p\u00e1gina s\u00f3lo se publican extractos de c\u00f3digo relevantes.<\/em><\/p>\n<h2><strong>El concepto<\/strong><\/h2>\n<p>Intentemos definir los requisitos de un sistema de este tipo:<\/p>\n<ul>\n<li>La principal caracter\u00edstica de un sistema de tareas temporizadas es poder especificar cu\u00e1ndo se ejecutar\u00e1 una determinada tarea en el tiempo. Esto se puede conseguir utilizando un campo ExecuteAt, que contendr\u00e1 el tiempo de ejecuci\u00f3n deseado (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Unix_time\" target=\"_blank\" rel=\"noopener noreferrer\">Hora Unix<\/a>en milisegundos).<\/li>\n<li>Un requisito del software moderno es que debe soportar un entorno multinodo, lo que significa que debe ser un sistema distribuido. Debemos asegurarnos de que varios trabajadores NO procesen las mismas tareas. Aqu\u00ed podemos usar una buena caracter\u00edstica de Couchbase, <a href=\"https:\/\/www.couchbase.com\/blog\/es\/optimistic-or-pessimistic-locking-which-one-should-you-pick\/\">cierre pesimista<\/a>que permitir\u00e1 a un trabajador obtener un documento y bloquearlo para que ning\u00fan otro trabajador pueda procesarlo.<\/li>\n<\/ul>\n<p>La siguiente es una posible estructura para representar nuestra tarea:<\/p>\n<pre class=\"lang:default decode:true\">type Task struct {\r\n    Id string\r\n\r\n    \/\/ The desired task execution time\r\n    ExecuteAt int64\r\n\r\n    \/\/ Task-specific content\r\n    Content string\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h2><strong>Caracter\u00edsticas de Couchbase<\/strong><\/h2>\n<p>En primer lugar, he aqu\u00ed una visi\u00f3n general de las caracter\u00edsticas de Couchbase que vamos a utilizar:<\/p>\n<h3>META()<\/h3>\n<p>Cada documento de un bucket de Couchbase tiene un documento META()asociado, que contiene informaci\u00f3n espec\u00edfica de la entidad del documento, como:<\/p>\n<ul>\n<li>id - la clave del documento dentro del cubo.<\/li>\n<li>cas - un n\u00famero int64, usado por Couchbase para prevenir <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.1\/sdk\/concurrent-mutations-cluster.html\" target=\"_blank\" rel=\"noopener noreferrer\">condiciones de carrera<\/a>\u00a0durante la edici\u00f3n de documentos.<\/li>\n<li>expiraci\u00f3n - cuando un documento est\u00e1 destinado a expirar, o 0 si nunca expirar\u00e1.<\/li>\n<\/ul>\n<p><em>Sugerencia<\/em>: Estos campos (por ejemplo, META().cas) <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.1\/n1ql\/n1ql-language-reference\/indexing-meta-info.html\" target=\"_blank\" rel=\"noopener noreferrer\">puede indexarse<\/a>\u00a0(a partir de Couchbase 5.0).<\/p>\n<h3><strong>CAS (Comprobar y fijar)<\/strong><\/h3>\n<p>Cuando se obtiene un documento, tambi\u00e9n se devuelve su valor CAS, y las llamadas posteriores para modificar el documento pueden especificar este valor para asegurarse de que van a editar la versi\u00f3n deseada del documento.<\/p>\n<p>Por ejemplo:<\/p>\n<ul>\n<li>El cliente A obtiene un documento y su valor CAS actual es 1234.<\/li>\n<li>El cliente B edita el documento, lo que altera el valor CAS a 5678.<\/li>\n<\/ul>\n<ol>\n<li>Si A intenta editar el documento sin proporcionar el valor CAS, la edici\u00f3n se realizar\u00e1 correctamente, pero los cambios realizados por B se perder\u00e1n.<\/li>\n<li>Si A intenta editar el documento proporcionando el valor CAS (1234), se devolver\u00e1 un error porque el actual (5678) es diferente. El cliente A tendr\u00e1 que recuperar el documento de nuevo y volver a ejecutar el proceso.<\/li>\n<\/ol>\n<p>El valor CAS es una herramienta extremadamente \u00fatil para asegurarnos de que no estamos reemplazando o alterando una versi\u00f3n incorrecta\/nueva de un documento, perdiendo sus cambios.<\/p>\n<h3><strong>Cierre pesimista<\/strong><\/h3>\n<p>Couchbase nos permite \"bloquear\" un documento, para que s\u00f3lo pueda ser le\u00eddo y escrito por un cliente a la vez, utilizando <a href=\"https:\/\/github.com\/couchbase\/gocb\/blob\/v1.3.3\/bucket_crud.go#L18\" target=\"_blank\" rel=\"noopener noreferrer\">gocb.GetAndLock<\/a>\u00a0Funci\u00f3n Go SDK.<\/p>\n<pre class=\"lang:default decode:true\">\/\/ Lock the document\r\nlockTime := 10 \/\/ seconds\r\nlockedCAS, err := bucket.GetAndLock(documentKey, lockTime, &amp;outStruct)\r\n\r\n\/\/ Unlock it\r\n_, err = bucket.Unlock(documentKey, lockedCAS)<\/pre>\n<p>&nbsp;<\/p>\n<p>Cuando un documento est\u00e1 bloqueado, cualquier otra solicitud para bloquearlo\/mutarlo\/desbloquearlo arrojar\u00e1 un error (sigue siendo posible simplemente obtener el documento), a menos que se utilice el valor CAS correcto.<\/p>\n<p>Nota: El tiempo m\u00e1ximo de bloqueo de un documento es de 15 segundos, y el uso de un valor lockTime de 0 har\u00e1 que se establezca el tiempo m\u00e1ximo. Esto crea una limitaci\u00f3n sobre cu\u00e1nto tiempo puede ejecutarse una tarea antes de ser marcada autom\u00e1ticamente como disponible (por tiempo de espera de bloqueo).<\/p>\n<p><em>Pista:<\/em>\u00a0Mientras un documento est\u00e1 bloqueado, su valor CAS devuelto es -1.<\/p>\n<h2><strong>Indexaci\u00f3n y consulta<\/strong><\/h2>\n<p>Cabe destacar que las dos sugerencias juntas nos indican que podemos indexar un campo (META().cas), que se convierte en -1 cuando un documento est\u00e1 bloqueado. Tambi\u00e9n significa que podemos consultar documentos bas\u00e1ndonos en esta condici\u00f3n.<\/p>\n<h3><strong>La consulta<\/strong><\/h3>\n<p>Intentemos definir una consulta que se ajuste a los requisitos:<\/p>\n<ul>\n<li>Queremos obtener un id de tarea, que puede ser utilizado m\u00e1s tarde para obtener y bloquear el documento: SELECT Id.<\/li>\n<li>La tarea no debe estar ya bloqueada: WHERE META().cas  -1.<\/li>\n<li>La tarea debe ejecutarse ahora: WHERE ExecuteAt &lt;= NOW_MILLIS() (<a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/current\/n1ql\/n1ql-language-reference\/datefun.html#story-h2-30\" target=\"_blank\" rel=\"noopener noreferrer\">AHORA_MILLIS<\/a>\u00a0devuelve el tiempo Unix actual en milisegundos).<\/li>\n<li>Necesitamos obtener la tarea m\u00e1s cercana en el tiempo, por lo que queremos ordenar las tareas por su tiempo de ejecuci\u00f3n: ORDER BY ExecuteAt ASC.<\/li>\n<li>Digamos por ahora (!!!) que un trabajador querr\u00e1 que s\u00f3lo se procese una tarea a la vez: LIMIT 1.<\/li>\n<\/ul>\n<p>El resultado deber\u00eda ser similar a esta consulta:<\/p>\n<pre class=\"lang:default decode:true\">SELECT `Id`\r\nFROM `timed_tasks` \/\/ Our bucket\r\nWHERE META().`cas` &lt;&gt; -1\r\nAND `ExecuteAt` &lt;= NOW_MILLIS()\r\nORDER BY `ExecuteAt` ASC\r\nLIMIT 1<\/pre>\n<p>Su ejecuci\u00f3n devolver\u00e1 un array similar a:<\/p>\n<pre class=\"lang:default decode:true\">[{\r\n    \"Id\": \"task_id_goes_here\"\r\n}]<\/pre>\n<p>&nbsp;<\/p>\n<h3><strong>El \u00edndice<\/strong><\/h3>\n<p>Ahora podemos planificar un \u00edndice espec\u00edfico para la consulta, optimizado para la ejecuci\u00f3n de la consulta en la que acabamos de pensar. Los \u00edndices espec\u00edficos de consulta son imprescindibles para mejorar el rendimiento de las consultas en bases de datos NoSQL.<\/p>\n<ul>\n<li>La consulta est\u00e1 comprobando que un documento no est\u00e1 bloqueado actualmente:\n<pre class=\"lang:default decode:true\">WHERE META().cas &lt;&gt; -1.<\/pre>\n<\/li>\n<li>Adem\u00e1s, est\u00e1 pidiendo directamente que el tiempo de ejecuci\u00f3n est\u00e9 en el pasado. Entonces necesitamos indexar el campo ExecuteAt.<br \/>\nLa consulta del \u00edndice podr\u00eda ser entonces la siguiente:<\/li>\n<\/ul>\n<pre class=\"lang:default decode:true\">CREATE INDEX `idx_timed_task`\r\nON `timed_tasks`\r\n(`ExecuteAt` ASC)\r\nWHERE META().`cas` &lt;&gt; -1<\/pre>\n<p>&nbsp;<\/p>\n<h3><strong>Optimizaci\u00f3n de la consulta<\/strong><\/h3>\n<p>Ahora podemos optimizar a\u00fan m\u00e1s la consulta:<\/p>\n<ul>\n<li>Podemos indicar a la consulta que utilice nuestro \u00edndice proporcionando una variable <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.1\/n1ql\/n1ql-language-reference\/hints.html\" target=\"_blank\" rel=\"noopener noreferrer\">pista<\/a>\u00a0a la misma: USE INDEX (idx_timed_task USING GSI).<\/li>\n<li>Podemos pedir a Couchbase que espere a que el \u00edndice est\u00e9 actualizado (normalmente la indexaci\u00f3n es un proceso as\u00edncrono) antes de ejecutar la consulta, de forma que nuestros resultados contengan con seguridad tareas desbloqueadas, proporcionando una directiva <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.1\/indexes\/performance-consistency.html\" target=\"_blank\" rel=\"noopener noreferrer\">coherencia<\/a>\u00a0requisito a nivel del SDK: query.Consistency(gocb.RequestPlus).<\/li>\n<\/ul>\n<h2><strong>El flujo<\/strong><\/h2>\n<p>Un posible flujo para el bucle de trabajador consumidor de tarea temporizada es:<\/p>\n<ol>\n<li>Consulta de un identificador de tarea disponible.<\/li>\n<li>Obtener y bloquear la tarea.<\/li>\n<li>Procesar la tarea.<\/li>\n<li>Eliminar la tarea.<\/li>\n<\/ol>\n<h3><strong>M\u00faltiples nodos<\/strong><\/h3>\n<p>Pensemos por un momento en c\u00f3mo una configuraci\u00f3n multinodo puede alterar este flujo.<\/p>\n<p>Si varios trabajadores van a consultar tareas disponibles de forma concurrente, probablemente encontrar\u00e1n la misma tarea, y s\u00f3lo uno de ellos podr\u00e1 procesarla con \u00e9xito, mientras que los dem\u00e1s trabajadores tendr\u00e1n que repetir el bucle (ejecutar una nueva consulta) para obtener nuevas tareas.<\/p>\n<p>Podemos aplicar entonces otro enfoque:<\/p>\n<ol>\n<li>Consulta de ids de tareas disponibles, limitando la cantidad de ids al n\u00famero de trabajadores.<\/li>\n<li>Para cada id de tarea, intente bloquear la tarea. Al primer bloqueo con \u00e9xito, pasa al 4.<\/li>\n<li>Si no se ha bloqueado ninguna tarea, repite el bucle.<\/li>\n<li>Procesar la tarea.<\/li>\n<li>Eliminar la tarea.<\/li>\n<\/ol>\n<p>En el mejor de los casos, cada trabajador podr\u00e1 bloquear con \u00e9xito una tarea al primer intento. En el peor de los casos, los trabajadores tendr\u00e1n que intentar bloquear varios documentos sin \u00e9xito. En una ejecuci\u00f3n media, los trabajadores bloquear\u00e1n las tareas con \u00e9xito, quiz\u00e1 despu\u00e9s de haber intentado bloquear algunas otras.<\/p>\n<p>Tenemos que llegar a un compromiso entre la frecuencia con la que queremos consultar la base de datos y el n\u00famero de intentos de bloqueo fallidos que podemos soportar. En general, intentar bloquear documentos ser\u00e1 mucho m\u00e1s r\u00e1pido que ejecutar consultas N1QL.<\/p>\n<h2><strong>El c\u00f3digo<\/strong><\/h2>\n<p>Veamos algunos ejemplos de c\u00f3digo relevantes:<\/p>\n<h3><strong>El productor<\/strong><\/h3>\n<p>La generaci\u00f3n de la tarea puede resumirse en esta funci\u00f3n:<\/p>\n<pre class=\"lang:default decode:true\">func NewTask(executeAt time.Time, content string) (*Task, error) {\r\n    if executeAt.IsZero() {\r\n        return nil, errors.New(\"executeAt must not be a zero time\")\r\n    }\r\n\r\n    taskUUID, err := uuid.NewV1() \/\/ github.com\/satori\/go.uuid\r\n    if err != nil {\r\n        return nil, err\r\n    }\r\n\r\n    \/\/ Convert time.Time to int64 milliseconds\r\n    executeAtMillis := executeAt.UnixNano() \/ int64(time.Millisecond)\r\n\r\n    task := Task{\r\n        Id:        taskUUID.String(),\r\n        ExecuteAt: executeAtMillis,\r\n        Content:   content,\r\n    }\r\n\r\n    return &amp;task, nil\r\n}\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Una vez que generamos un objeto de tarea v\u00e1lido, podemos simplemente insertarlo en nuestro cubo con:<\/p>\n<pre class=\"lang:default decode:true\">_, err := controller.bucket.Insert(task.Id, task, 0)<\/pre>\n<p>&nbsp;<\/p>\n<h3><strong>El consumidor<\/strong><\/h3>\n<p>Podemos obtener y bloquear un documento por id, usando este c\u00f3digo:<\/p>\n<pre class=\"lang:default decode:true\">\/\/ Using zero values for lock time will set the maximum time available.\r\ntask := new(Task)\r\nlockedCAS, err := controller.bucket.GetAndLock(taskId, 0, &amp;task)<\/pre>\n<p>Se puede eliminar una tarea utilizando este c\u00f3digo:<\/p>\n<pre class=\"lang:default decode:true\">_, err := controller.bucket.Remove(taskId, lockedCAS)<\/pre>\n<p>El c\u00f3digo del consumidor principal puede resumirse con el siguiente fragmento:<\/p>\n<pre class=\"lang:default decode:true\">taskIds, err := couchbaseController.QueryNextTaskIds(consumersCount)\r\n...\r\n\r\nif len(taskIds) == 0 {\r\n    ...\r\n    \/\/ No tasks have been found, restart the loop\r\n}\r\n\r\nvar taskId string\r\nvar task *internal.Task\r\nvar lockedCAS gocb.Cas\r\n\r\nfor _, taskId = range taskIds {\r\n    \/\/ Lock and get the task, so that only this consumer will process it\r\n    task, lockedCAS, err = couchbaseController.GetAndLockTask(taskId)\r\n    if err != nil {\r\n        ...\r\n        \/\/ Error getting the task, proceed to next one in list\r\n        continue\r\n    }\r\n\r\n    \/\/ Successfully locked task!\r\n    \/\/ Move out to process it\r\n    break\r\n}\r\n\r\nif task == nil {\r\n    ...\r\n    \/\/ No tasks could be locked, restart loop\r\n}\r\n\r\n\/\/ Actual processing of the task\r\n\/\/ Improvement: could also return an error, which would let the task be\r\n\/\/ processed by another worker later.\r\nprocessTask(task)\r\n\r\n\/*\r\nRemove the task from Couchbase.\r\nThe task will be currently locked, which means we need to provide the\r\ncurrent CAS value, so that the producer is authorized to remove it.\r\n *\/\r\nerr = couchbaseController.RemoveTask(taskId, lockedCAS)\r\n...\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h2><strong>Conclusi\u00f3n<\/strong><\/h2>\n<p>En este post hemos visto una forma de crear un sistema fiable de tareas cronometradas distribuidas usando Couchbase y Go.<\/p>\n<p>Este sistema podr\u00eda seguir desarroll\u00e1ndose:<\/p>\n<ul>\n<li>Soporte para el tratamiento de errores.<\/li>\n<li>Implementar una funci\u00f3n de reintento (si el procesamiento falla, reprogramar la tarea en el futuro).<\/li>\n<li>Mejora de la l\u00f3gica de bloqueo mediante:\n<ul>\n<li>Ajuste del n\u00famero m\u00e1ximo de identificadores de tarea devueltos (en lugar del recuento de trabajadores por defecto).<\/li>\n<li>Soportar una duraci\u00f3n de procesamiento de tareas superior a 15 segundos (el tiempo m\u00e1ximo de bloqueo de un documento en Couchbase).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Gracias por su tiempo y \u00a1feliz desarrollo!<\/p>\n<p style=\"text-align: center\"><em>Este post forma parte del <a href=\"https:\/\/www.couchbase.com\/blog\/es\/community\/community-writers-program\/\" target=\"_blank\" rel=\"noopener noreferrer\">Programa de escritura comunitaria<\/a><\/em><\/p>","protected":false},"excerpt":{"rendered":"<p>Alberto Marchetti is a full-stack developer, and author of\u00a0\u201cRenderScript: parallel computing on Android, the easy way.\u201d\u00a0He is always living on the edge by constantly jumping into the discovery of modern languages and technologies. &nbsp; Timed tasks\u00a0using Couchbase and Go In [&hellip;]<\/p>","protected":false},"author":53,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1816,1820],"tags":[],"ppma_author":[9026],"class_list":["post-4852","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-server","category-golang"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Timed tasks using Couchbase and Go - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"See how to use the Couchbase indexing system to create a timed-tasks distributed system using Couchbase and Go. Also, check some Couchbase features.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/es\/timed-tasks-using-couchbase-go\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Timed tasks using Couchbase and Go\" \/>\n<meta property=\"og:description\" content=\"See how to use the Couchbase indexing system to create a timed-tasks distributed system using Couchbase and Go. Also, check some Couchbase features.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/timed-tasks-using-couchbase-go\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2018-03-19T18:50:44+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T04:20:32+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/06\/CB-Blog_red-black-big.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Laura Czajkowski, Developer Community Manager, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/06\/CB-Blog_red-black-big.png\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Laura Czajkowski, Developer Community Manager, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/\"},\"author\":{\"name\":\"Laura Czajkowski, Developer Community Manager, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220\"},\"headline\":\"Timed tasks using Couchbase and Go\",\"datePublished\":\"2018-03-19T18:50:44+00:00\",\"dateModified\":\"2025-06-14T04:20:32+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/\"},\"wordCount\":1311,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"articleSection\":[\"Couchbase Server\",\"GoLang\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/\",\"name\":\"Timed tasks using Couchbase and Go - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2018-03-19T18:50:44+00:00\",\"dateModified\":\"2025-06-14T04:20:32+00:00\",\"description\":\"See how to use the Couchbase indexing system to create a timed-tasks distributed system using Couchbase and Go. Also, check some Couchbase features.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Timed tasks using Couchbase and Go\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220\",\"name\":\"Laura Czajkowski, Developer Community Manager, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/9deb07d5daaa00220534c31768bc4409\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g\",\"caption\":\"Laura Czajkowski, Developer Community Manager, Couchbase\"},\"description\":\"Laura Czajkowski is the Snr. Developer Community Manager at Couchbase overseeing the community. She\u2019s responsible for our monthly developer newsletter.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/es\/author\/laura-czajkowski\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Timed tasks using Couchbase and Go - The Couchbase Blog","description":"Mira c\u00f3mo usar el sistema de indexaci\u00f3n de Couchbase para crear un sistema distribuido de tareas cronometradas usando Couchbase y Go. Adem\u00e1s, revisa algunas caracter\u00edsticas de Couchbase.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/es\/timed-tasks-using-couchbase-go\/","og_locale":"es_MX","og_type":"article","og_title":"Timed tasks using Couchbase and Go","og_description":"See how to use the Couchbase indexing system to create a timed-tasks distributed system using Couchbase and Go. Also, check some Couchbase features.","og_url":"https:\/\/www.couchbase.com\/blog\/es\/timed-tasks-using-couchbase-go\/","og_site_name":"The Couchbase Blog","article_published_time":"2018-03-19T18:50:44+00:00","article_modified_time":"2025-06-14T04:20:32+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/06\/CB-Blog_red-black-big.png","type":"image\/png"}],"author":"Laura Czajkowski, Developer Community Manager, Couchbase","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/06\/CB-Blog_red-black-big.png","twitter_misc":{"Written by":"Laura Czajkowski, Developer Community Manager, Couchbase","Est. reading time":"6 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/"},"author":{"name":"Laura Czajkowski, Developer Community Manager, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220"},"headline":"Timed tasks using Couchbase and Go","datePublished":"2018-03-19T18:50:44+00:00","dateModified":"2025-06-14T04:20:32+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/"},"wordCount":1311,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","articleSection":["Couchbase Server","GoLang"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/","url":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/","name":"Timed tasks using Couchbase and Go - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2018-03-19T18:50:44+00:00","dateModified":"2025-06-14T04:20:32+00:00","description":"Mira c\u00f3mo usar el sistema de indexaci\u00f3n de Couchbase para crear un sistema distribuido de tareas cronometradas usando Couchbase y Go. Adem\u00e1s, revisa algunas caracter\u00edsticas de Couchbase.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Timed tasks using Couchbase and Go"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"El blog de Couchbase","description":"Couchbase, la base de datos NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"El blog de Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220","name":"Laura Czajkowski, Directora de la Comunidad de Desarrolladores, Couchbase","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/9deb07d5daaa00220534c31768bc4409","url":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","caption":"Laura Czajkowski, Developer Community Manager, Couchbase"},"description":"Laura Czajkowski es la Snr. Developer Community Manager en Couchbase supervisando la comunidad. Es responsable de nuestro bolet\u00edn mensual para desarrolladores.","url":"https:\/\/www.couchbase.com\/blog\/es\/author\/laura-czajkowski\/"}]}},"authors":[{"term_id":9026,"user_id":53,"is_guest":0,"slug":"laura-czajkowski","display_name":"Laura Czajkowski, Developer Community Manager, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","author_category":"","last_name":"Czajkowski","first_name":"Laura","job_title":"","user_url":"","description":"Laura Czajkowski es la Snr. Developer Community Manager en Couchbase supervisando la comunidad. Es responsable de nuestro bolet\u00edn mensual para desarrolladores."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/4852","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/users\/53"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/comments?post=4852"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/4852\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media?parent=4852"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=4852"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=4852"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=4852"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}