diff --git a/inc/lektor/reg.h b/inc/lektor/reg.h
index c2cc7494fd8e3cf18c3200f5d6722c29f75c7641..9439439d1f63e3ad939160a70a5e6f60c8a0ee16 100644
--- a/inc/lektor/reg.h
+++ b/inc/lektor/reg.h
@@ -46,9 +46,15 @@ struct lkt_module {
     REG_DECLARE(reg)                    \
     static struct module_reg *as = reg;
 
-/* Call a function from a reg. */
+/* Call a function from a reg.
+ * NOTE:
+ * - Use the MOD_CALL macro to call a function that takes arguments
+ * - Use the MOD_PROC macro to call a procedure, i.e. a functions
+ *   that doesn't take arguments */
 #define MOD_CALL(module, name, ...)     \
     reg_call((module).reg, name, 1 + (GET_VA_COUNT(__VA_ARGS__)), &(module).data, __VA_ARGS__)
+#define MOD_PROC(module, name)          \
+    reg_call((module).reg, name, 1, &(module).data)
 int reg_call(struct module_reg *reg, const char *name, int count, ...);
 
 /* Import a module, from a file (mod is a filepath) or from the __reg__ in the
diff --git a/src/base/commands.c b/src/base/commands.c
index 6795fd4b29fa9198a4b5d9e230f37ab2c88d8746..2795b388fd78ffe8aeec9e72c42c83e668eeaea7 100644
--- a/src/base/commands.c
+++ b/src/base/commands.c
@@ -58,17 +58,7 @@ command_update(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]
     RETURN_UNLESS(lkt_client_auth(srv, c, false), "Failed to authentificate user", false);
     srv->mpd_idle_events |= MPD_IDLE_UPDATE;
     srv->mpd_idle_events |= MPD_IDLE_DATABASE;
-    return ! MOD_CALL(srv->repo_mod, "update", 0);
-}
-
-static inline void *
-__rescan(void *arg)
-{
-    struct lkt_state *srv = ((struct lkt_state **) arg)[0];
-    bool forced = * ((bool *) & ((struct lkt_state **) arg)[1]);
-    free(arg);
-    database_update(srv->db, srv->kara_prefix, !forced);
-    return NULL;
+    return ! MOD_PROC(srv->repo_mod, "update");
 }
 
 bool
@@ -78,14 +68,7 @@ command_rescan(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]
     RETURN_UNLESS(lkt_client_auth(srv, c, false), "Failed to authentificate user", false);
     srv->mpd_idle_events |= MPD_IDLE_UPDATE;
     srv->mpd_idle_events |= MPD_IDLE_DATABASE;
-    void *args = malloc(sizeof(struct lkt_state *) + sizeof(bool));
-    ((struct lkt_state **) args)[0] = srv;
-    * ((bool *) & ((struct lkt_state **) args)[1]) = forced;
-    // return ! mthread_create(NULL, ATTR_DETACHED_FREE, __rescan, args);
-    /* TODO: Use the repo module. */
-    (void) __rescan;
-    LOG_ERROR("GENERAL", "Not implemented");
-    return false;
+    return ! MOD_PROC(srv->repo_mod, "rescan");
 }
 
 inline bool
@@ -184,7 +167,7 @@ command_pause(struct lkt_state *srv, char __attribute__((unused)) *args[LKT_MESS
     srv->mpd_idle_events |= MPD_IDLE_PLAYER;
     if (!database_queue_toggle_pause(srv->db))
         return false;
-    return ! MOD_CALL(srv->window_mod, "toggle", 1);
+    return ! MOD_PROC(srv->window_mod, "toggle");
 }
 
 bool
@@ -260,7 +243,7 @@ bool
 command_stop(struct lkt_state *srv, char __attribute__((unused))  *args[LKT_MESSAGE_ARGS_MAX])
 {
     RETURN_UNLESS(database_queue_stop(srv->db), "DB error", false);
-    MOD_CALL(srv->window_mod, "close", 1);
+    MOD_PROC(srv->window_mod, "close");
     srv->mpd_idle_events |= MPD_IDLE_PLAYER;
     return true;
 }
@@ -330,7 +313,7 @@ command_delid(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX])
 
         else {
             LOG_WARN("COMMAND", "Failed to skip current kara to delete id %ld, stop playback", id);
-            MOD_CALL(srv->window_mod, "close", 1);
+            MOD_PROC(srv->window_mod, "close");
         }
     }
 
diff --git a/src/module/module_repo.c b/src/module/module_repo.c
index 7fedced80272d1591e6e8b3b8921cabdcafafdda..a368648b494aa931c2cd7e36d15dd84c9cfbad7c 100644
--- a/src/module/module_repo.c
+++ b/src/module/module_repo.c
@@ -63,15 +63,6 @@ struct __file {
     int fd;
 };
 
-/************************
- * Function definitions *
- ************************/
-
-static bool module_repo_new(struct module_repo_internal *, struct queue *, volatile sqlite3 *);
-static void module_repo_close(struct module_repo_internal *);
-static void module_repo_free(struct module_repo_internal *);
-__attribute__((unused)) static void module_repo_update(struct module_repo_internal *);
-
 /*********************
  * Private functions *
  *********************/
@@ -179,8 +170,19 @@ err:
 static void *
 __worker_update(void *__repo)
 {
+    /* TODO: Notify update in progress */
+    struct module_repo_internal *repo = __repo;
+    repo->updating = 1;
+    pthread_exit(NULL);
+}
+
+static void *
+__worker_rescan(void *__repo)
+{
+    /* TODO: Notify rescan in progress */
     struct module_repo_internal *repo = __repo;
     repo->updating = 1;
+    /* Use the database_update(db, prefix, forced) function here ! */
     pthread_exit(NULL);
 }
 
@@ -191,23 +193,7 @@ __worker_update(void *__repo)
 static inline void
 module_repo_close(struct module_repo_internal *repo)
 {
-    UNUSED(repo);
-    /* TODO: Join all threads */
-}
-
-static void
-module_repo_free(struct module_repo_internal *repo)
-{
-    UNUSED(repo);
-    module_repo_close(repo);
-    --__curl_init;
-    if (!__curl_init)
-        curl_global_cleanup();
-    free(repo->kara_dir);
-    free(repo->get_id_json);
-    free(repo->get_id_file);
-    free(repo->base_url);
-    free(repo->get_all_json);
+    worker_pool_waitall(&repo->workers);
 }
 
 static bool
@@ -255,11 +241,6 @@ module_repo_new(struct module_repo_internal *repo_, struct queue *queue, volatil
     return 0;
 }
 
-static void
-module_repo_update(struct module_repo_internal __attribute__((unused)) *self)
-{
-}
-
 /********************
  * Export functions *
  ********************/
@@ -305,7 +286,17 @@ mod_free(va_list *va)
     struct module_repo_internal **repo;
     va_copy(copy, *va);
     repo = (struct module_repo_internal **) va_arg(copy, void **);
-    module_repo_free(*repo);
+
+    module_repo_close(*repo);
+    --__curl_init;
+    if (!__curl_init)
+        curl_global_cleanup();
+    free((*repo)->kara_dir);
+    free((*repo)->get_id_json);
+    free((*repo)->get_id_file);
+    free((*repo)->base_url);
+    free((*repo)->get_all_json);
+
     va_end(copy);
     return 0;
 }
@@ -324,6 +315,7 @@ mod_update(va_list *va)
         return 0;
     }
     (*repo)->updating = 1;
+    /* TODO: Notify update pending */
     if (worker_pool_push(&(*repo)->workers, __worker_update, (void *) *repo)) {
         LOG_ERROR("REPO", "Out of memory");
         va_end(copy);
@@ -331,7 +323,33 @@ mod_update(va_list *va)
     }
 
     va_end(copy);
-    LOG_INFO("REPO", "Update started");
+    LOG_INFO("REPO", "Update started (update)");
+    return 0;
+}
+
+static int
+mod_rescan(va_list *va)
+{
+    va_list copy;
+    struct module_repo_internal **repo;
+    va_copy(copy, *va);
+    repo = (struct module_repo_internal **) va_arg(copy, void **);
+
+    if ((*repo)->updating) {
+        LOG_WARN("REPO", "Already updating");
+        va_end(copy);
+        return 0;
+    }
+    (*repo)->updating = 1;
+    /* TODO: Notify update pending */
+    if (worker_pool_push(&(*repo)->workers, __worker_rescan, (void *) *repo)) {
+        LOG_ERROR("REPO", "Out of memory");
+        va_end(copy);
+        return 1;
+    }
+
+    va_end(copy);
+    LOG_INFO("REPO", "Update started (rescan)");
     return 0;
 }
 
@@ -340,6 +358,7 @@ REG_ADD_NAMED("new",    mod_new)
 REG_ADD_NAMED("free",   mod_free)
 REG_ADD_NAMED("close",  mod_close)
 REG_ADD_NAMED("update", mod_update)
+REG_ADD_NAMED("rescan", mod_rescan)
 REG_END()
 #if ! defined (LKT_STATIC_MODULE)
     REG_EXPORT(repo_reg)