Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion loopdb/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func NewPostgresStore(cfg *PostgresConfig,
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

err = baseDB.FixFaultyTimestamps(ctx, parsePostgresTimeStamp)
err = baseDB.FixFaultyTimestamps(ctx)
if err != nil {
log.Errorf("Failed to fix faulty timestamps: %v", err)
return nil, err
Expand Down
47 changes: 41 additions & 6 deletions loopdb/sql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,19 +375,54 @@ func TestIssue615(t *testing.T) {
require.NoError(t, err)
}

parseFunc := parseSqliteTimeStamp
if testDBType == "postgres" {
parseFunc = parsePostgresTimeStamp
}

// Fix the faulty timestamp.
err = sqlDB.FixFaultyTimestamps(ctxb, parseFunc)
err = sqlDB.FixFaultyTimestamps(ctxb)
require.NoError(t, err)

_, err = sqlDB.GetLoopOutSwaps(ctxb)
require.NoError(t, err)
}

func TestTimeConversions(t *testing.T) {
tests := []struct {
timeString string
expectedTime time.Time
}{
{
timeString: "2018-11-01 00:00:00 +0000 UTC",
expectedTime: time.Date(2018, 11, 1, 0, 0, 0, 0, time.UTC),
},
{
timeString: "2018-11-01 00:00:01.10000 +0000 UTC",
expectedTime: time.Date(2018, 11, 1, 0, 0, 1, 0, time.UTC),
},
{
timeString: "2053-12-29T02:40:44.269009408Z",
expectedTime: time.Date(
2053, 12, 29, 2, 40, 44, 0, time.UTC,
),
},
{
timeString: "55563-06-27 02:09:24 +0000 UTC",
expectedTime: time.Date(
55563, 6, 27, 2, 9, 24, 0, time.UTC,
),
},
{
timeString: "2172-03-11 10:01:11.849906176 +0000 UTC",
expectedTime: time.Date(
2172, 3, 11, 10, 1, 11, 0, time.UTC,
),
},
}

for _, test := range tests {
time, err := parseTimeStamp(test.timeString)
require.NoError(t, err)
require.Equal(t, test.expectedTime, time)
}
}

const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func randomString(length int) string {
Expand Down
29 changes: 23 additions & 6 deletions loopdb/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func NewSqliteStore(cfg *SqliteConfig, network *chaincfg.Params) (*SqliteSwapSto
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

err = baseDB.FixFaultyTimestamps(ctx, parseSqliteTimeStamp)
err = baseDB.FixFaultyTimestamps(ctx)
if err != nil {
log.Errorf("Failed to fix faulty timestamps: %v", err)
return nil, err
Expand Down Expand Up @@ -209,8 +209,7 @@ func (db *BaseDB) ExecTx(ctx context.Context, txOptions TxOptions,

// FixFaultyTimestamps fixes faulty timestamps in the database, caused
// by using milliseconds instead of seconds as the publication deadline.
func (b *BaseDB) FixFaultyTimestamps(ctx context.Context,
parseTimeFunc func(string) (time.Time, error)) error {
func (b *BaseDB) FixFaultyTimestamps(ctx context.Context) error {

// Manually fetch all the loop out swaps.
rows, err := b.DB.QueryContext(
Expand Down Expand Up @@ -248,7 +247,7 @@ func (b *BaseDB) FixFaultyTimestamps(ctx context.Context,
defer tx.Rollback() //nolint: errcheck

for _, swap := range loopOutSwaps {
faultyTime, err := parseTimeFunc(swap.PublicationDeadline)
faultyTime, err := parseTimeStamp(swap.PublicationDeadline)
if err != nil {
return err
}
Expand Down Expand Up @@ -309,14 +308,29 @@ func (r *SqliteTxOptions) ReadOnly() bool {
return r.readOnly
}

// parseTimeStamp tries to parse a timestamp string with both the
// parseSqliteTimeStamp and parsePostgresTimeStamp functions.
// If both fail, it returns an error.
func parseTimeStamp(dateTimeStr string) (time.Time, error) {
t, err := parseSqliteTimeStamp(dateTimeStr)
if err != nil {
t, err = parsePostgresTimeStamp(dateTimeStr)
if err != nil {
return time.Time{}, err
}
}

return t, nil
}

// parseSqliteTimeStamp parses a timestamp string in the format of
// "YYYY-MM-DD HH:MM:SS +0000 UTC" and returns a time.Time value.
// NOTE: we can't use time.Parse() because it doesn't support having years
// with more than 4 digits.
func parseSqliteTimeStamp(dateTimeStr string) (time.Time, error) {
// Split the date and time parts.
parts := strings.Fields(strings.TrimSpace(dateTimeStr))
if len(parts) <= 2 {
if len(parts) < 2 {
return time.Time{}, fmt.Errorf("invalid timestamp format: %v",
dateTimeStr)
}
Expand Down Expand Up @@ -385,7 +399,10 @@ func parseTimeParts(datePart, timePart string) (time.Time, error) {
return time.Time{}, err
}

second, err := strconv.Atoi(timeParts[2])
// Parse the seconds and ignore the fractional part.
secondParts := strings.Split(timeParts[2], ".")

second, err := strconv.Atoi(secondParts[0])
if err != nil {
return time.Time{}, err
}
Expand Down