Implement safepoints
This commit is contained in:
		
							parent
							
								
									7e08b8e830
								
							
						
					
					
						commit
						cba0886b24
					
				@ -4,26 +4,28 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
 | 
			
		||||
	_ "github.com/localhots/mysql" // MySQL driver
 | 
			
		||||
 | 
			
		||||
	"github.com/juju/errors"
 | 
			
		||||
	"github.com/localhots/bocadillo/binlog"
 | 
			
		||||
	"github.com/localhots/bocadillo/mysql"
 | 
			
		||||
	"github.com/localhots/bocadillo/reader/schema"
 | 
			
		||||
	"github.com/localhots/bocadillo/reader/slave"
 | 
			
		||||
	_ "github.com/localhots/mysql" // MySQL driver
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// EnhancedReader is an extended version of the reader that maintains schema
 | 
			
		||||
// details to add column names and signed integers support.
 | 
			
		||||
type EnhancedReader struct {
 | 
			
		||||
	reader    *Reader
 | 
			
		||||
	safepoint binlog.Position
 | 
			
		||||
	schemaMgr *schema.Manager
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnhancedRowsEvent ...
 | 
			
		||||
type EnhancedRowsEvent struct {
 | 
			
		||||
	Type  binlog.EventType
 | 
			
		||||
	Table binlog.TableDescription
 | 
			
		||||
	Rows  []map[string]interface{}
 | 
			
		||||
	Header binlog.EventHeader
 | 
			
		||||
	Table  binlog.TableDescription
 | 
			
		||||
	Rows   []map[string]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewEnhanced creates a new enhanced binary log reader.
 | 
			
		||||
@ -41,6 +43,7 @@ func NewEnhanced(dsn string, sc slave.Config) (*EnhancedReader, error) {
 | 
			
		||||
	return &EnhancedReader{
 | 
			
		||||
		reader:    r,
 | 
			
		||||
		schemaMgr: schema.NewManager(conn),
 | 
			
		||||
		safepoint: r.state,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -121,9 +124,9 @@ func (r *EnhancedReader) nextRowsEvent() (*EnhancedRowsEvent, error) {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ere := EnhancedRowsEvent{
 | 
			
		||||
			Type:  re.Type,
 | 
			
		||||
			Table: *evt.Table,
 | 
			
		||||
			Rows:  make([]map[string]interface{}, len(re.Rows)),
 | 
			
		||||
			Header: evt.Header,
 | 
			
		||||
			Table:  *evt.Table,
 | 
			
		||||
			Rows:   make([]map[string]interface{}, len(re.Rows)),
 | 
			
		||||
		}
 | 
			
		||||
		for i, row := range re.Rows {
 | 
			
		||||
			erow := make(map[string]interface{}, len(row))
 | 
			
		||||
@ -145,11 +148,26 @@ func (r *EnhancedReader) nextRowsEvent() (*EnhancedRowsEvent, error) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *EnhancedReader) processEvent(evt Event) {
 | 
			
		||||
	switch evt.Header.Type {
 | 
			
		||||
	case binlog.EventTypeFormatDescription, binlog.EventTypeTableMap, binlog.EventTypeXID:
 | 
			
		||||
		r.safepoint.Offset = evt.Offset
 | 
			
		||||
	case binlog.EventTypeRotate:
 | 
			
		||||
		r.safepoint = r.reader.state
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// State returns current position in the binary log.
 | 
			
		||||
func (r *EnhancedReader) State() binlog.Position {
 | 
			
		||||
	return r.reader.state
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Safepoint returns last encountered position that is considered safe to start
 | 
			
		||||
// with.
 | 
			
		||||
func (r *EnhancedReader) Safepoint() binlog.Position {
 | 
			
		||||
	return r.safepoint
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close underlying database connection.
 | 
			
		||||
func (r *EnhancedReader) Close() error {
 | 
			
		||||
	return r.reader.Close()
 | 
			
		||||
 | 
			
		||||
@ -19,11 +19,18 @@ type Event struct {
 | 
			
		||||
	Format binlog.FormatDescription
 | 
			
		||||
	Header binlog.EventHeader
 | 
			
		||||
	Buffer []byte
 | 
			
		||||
	Offset uint64
 | 
			
		||||
 | 
			
		||||
	// Table is not empty for rows events
 | 
			
		||||
	Table *binlog.TableDescription
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// ErrUnknownTableID is returned when a table ID from a rows event is
 | 
			
		||||
	// missing in the table map index.
 | 
			
		||||
	ErrUnknownTableID = errors.New("Unknown table ID")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// New creates a new binary log reader.
 | 
			
		||||
func New(dsn string, sc slave.Config) (*Reader, error) {
 | 
			
		||||
	conn, err := slave.Connect(dsn, sc)
 | 
			
		||||
@ -112,7 +119,7 @@ func (r *Reader) ReadEvent() (*Event, error) {
 | 
			
		||||
		tableID, flags := re.PeekTableIDAndFlags(evt.Buffer, r.format)
 | 
			
		||||
		td, ok := r.tableMap[tableID]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return nil, errors.New("Unknown table ID")
 | 
			
		||||
			return nil, ErrUnknownTableID
 | 
			
		||||
		}
 | 
			
		||||
		evt.Table = &td
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user