@@ -15,6 +15,7 @@ import (
1515 _ "github.com/mattn/go-sqlite3"
1616
1717 "github.com/walterwanderley/sqlite-http-cache/config"
18+ "github.com/walterwanderley/sqlite-http-cache/db"
1819 _ "github.com/walterwanderley/sqlite-http-cache/extension"
1920)
2021
2627 timeout uint
2728 insecure bool
2829 ignoreStatusError bool
29- responseTableName string
30+ responseTables string
3031
3132 oauth2ClientID string
3233 oauth2ClientSecret string
@@ -41,12 +42,12 @@ func main() {
4142 // Scheduler strategy
4243 flag .DurationVar (& interval , "check-interval" , 30 * time .Second , "Interval to wait for check expired data" )
4344 flag .UintVar (& ttl , "ttl" , 30 * 60 , "Time to Live in seconds" )
44- flag .StringVar (& matchURL , "match-url" , "" , "Filter URLs" )
45+ flag .StringVar (& matchURL , "match-url" , "% " , "Filter URLs (SQL syntax) " )
4546 // Request/Store config
4647 flag .UintVar (& timeout , "timeout" , 30 * 1000 , "Timeout in milliseconds" )
4748 flag .BoolVar (& insecure , "insecure" , false , "Disable TLS verification" )
4849 flag .BoolVar (& ignoreStatusError , "ignore-status-error" , false , "ignore responses with status code != 2xx" )
49- flag .StringVar (& responseTableName , "response-table " , config . DefaultResponseTableName , "Database table used to store response data" )
50+ flag .StringVar (& responseTables , "response-tables " , "" , "Comma separated list of database tables used to store response data" )
5051 // Oauth2 Client Credentials
5152 flag .StringVar (& oauth2ClientID , "oauth2-client-id" , "" , "Oauth2 Client ID" )
5253 flag .StringVar (& oauth2ClientSecret , "oauth2-client-secret" , "" , "Oauth2 Client Secret" )
@@ -57,39 +58,50 @@ func main() {
5758 flag .StringVar (& caFile , "ca-file" , "" , "Path to the CA file" )
5859 flag .Parse ()
5960
60- if len (strings .TrimSpace (responseTableName )) == 0 {
61- log .Fatalf ("response-table cannot be empty" )
62- }
63-
6461 args := flag .Args ()
6562 if len (args ) != 1 {
6663 log .Fatalf ("Usage: %s <flags> [DSN]\n \n Example:\n \t %s file:example.db?_journal=WAL&_sync=NORMAL&_timeout=5000&_txlock=immediate\n " , os .Args [0 ], os .Args [0 ])
6764 }
6865 dsn := args [0 ]
6966
70- db , err := sql .Open ("sqlite3" , dsn )
67+ sqlDB , err := sql .Open ("sqlite3" , dsn )
7168 if err != nil {
7269 log .Fatalf ("cannot connect to the database: %v" , err )
7370 }
74- defer db .Close ()
71+ defer sqlDB .Close ()
72+
73+ var tableList []string
74+ if responseTables == "" {
75+ tableList , err = db .ResponseTables (sqlDB )
76+ if err != nil {
77+ log .Fatalf ("discovery response tables: %v" , err )
78+ }
79+ } else {
80+ tableList = strings .Split (responseTables , "," )
7581
76- _ , err = db .Exec (fmt .Sprintf ("CREATE VIRTUAL TABLE temp.http_refresh USING http_request(%s)" , opts ()))
77- if err != nil {
78- log .Fatalf ("error creating virtual table: %v" , err )
7982 }
8083
81- stmt , err := db .Prepare (fmt .Sprintf (`INSERT INTO temp.http_refresh(url)
84+ stmts := make (map [string ]* sql.Stmt )
85+ for _ , responseTableName := range tableList {
86+ _ , err = sqlDB .Exec (fmt .Sprintf ("CREATE VIRTUAL TABLE temp.%s_refresh USING http_request(%s)" , responseTableName , opts (responseTableName )))
87+ if err != nil {
88+ log .Fatalf ("error creating virtual table: %v" , err )
89+ }
90+
91+ stmt , err := sqlDB .Prepare (fmt .Sprintf (`INSERT INTO temp.%s_refresh(url)
8292 SELECT url FROM %s
83- WHERE url LIKE ? AND unixepoch() - unixepoch(timestamp) > ?` , responseTableName ))
84- if err != nil {
85- log .Fatalf ("error preparing statement: %v" , err )
93+ WHERE url LIKE ? AND unixepoch() - unixepoch(timestamp) > ?` , responseTableName , responseTableName ))
94+ if err != nil {
95+ log .Fatalf ("error preparing statement: %v" , err )
96+ }
97+ defer stmt .Close ()
98+ stmts [responseTableName ] = stmt
8699 }
87- defer stmt .Close ()
88100
89101 done := make (chan os.Signal , 1 )
90102 signal .Notify (done , os .Interrupt , syscall .SIGINT , syscall .SIGTERM )
91103
92- refreshData (stmt )
104+ refreshData (stmts )
93105 if interval == 0 {
94106 return
95107 }
@@ -102,27 +114,29 @@ func main() {
102114 for {
103115 select {
104116 case <- ticker .C :
105- refreshData (stmt )
117+ refreshData (stmts )
106118 case <- done :
107119 return
108120 }
109121 }
110122}
111123
112- func refreshData (stmt * sql.Stmt ) {
124+ func refreshData (stmts map [ string ] * sql.Stmt ) {
113125 slog .Info ("starting data verification" )
114126
115- res , err := stmt .Exec (matchURL , ttl )
116- if err != nil {
117- slog .Error ("error refreshing data" , "error" , err )
118- return
119- }
127+ for tableName , stmt := range stmts {
128+ res , err := stmt .Exec (matchURL , ttl )
129+ if err != nil {
130+ slog .Error ("error refreshing data" , "error" , err , "table" , tableName )
131+ continue
132+ }
120133
121- rowsAffected , _ := res .RowsAffected ()
122- slog .Info ("verification finished" , "rows_affected" , rowsAffected )
134+ rowsAffected , _ := res .RowsAffected ()
135+ slog .Info ("verification finished" , "rows_affected" , rowsAffected , "table" , tableName )
136+ }
123137}
124138
125- func opts () string {
139+ func opts (responseTableName string ) string {
126140 opts := make ([]string , 0 )
127141 opts = append (opts , fmt .Sprintf ("%s='%d'" , config .Timeout , timeout ))
128142 opts = append (opts , fmt .Sprintf ("%s='%v'" , config .Insecure , insecure ))
0 commit comments