// NewPostgresReadRepository creates a new PostgresReadRepository. func NewPostgresReadRepository(conn, table string) (*PostgresReadRepository, error) { lgr := lager.Child() lgr.Set("table", table) db, err := initDB(conn) if err != nil { return nil, err } create := fmt.Sprintf(` CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA public; CREATE TABLE IF NOT EXISTS %s ( data jsonb ); `, table) _, err = db.Exec(create) if err != nil { return nil, ErrCouldNotCreateTables } stmts := map[string]string{ "save": fmt.Sprintf("INSERT INTO %s (data) VALUES ($1)", table), "find": fmt.Sprintf("SELECT * FROM %s WHERE data->>'id'=$1", table), "findall": fmt.Sprintf("SELECT * FROM %s", table), "remove": fmt.Sprintf("DELETE FROM %s WHERE data->>'id'=$1", table), "clear": fmt.Sprintf("DELETE FROM %s", table), "update": fmt.Sprintf("UPDATE %s set data=$1 WHERE data->>'id'=$2", table), } return &PostgresReadRepository{ db: db, table: table, stmts: stmts, lgr: lgr, }, nil }
// NewPostgresEventStore creates a new PostgresEventStore. func NewPostgresEventStore(eventBus EventBus, conn string) (*PostgresEventStore, error) { lgr := lager.Child() db, err := initDB(conn) if err != nil { lgr.WithError(err).Errorf("Unable to initialize database") return nil, err } if _, err = db.Exec(` CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA public; CREATE TABLE IF NOT EXISTS aggregrates ( id uuid NOT NULL, version int NOT NULL ); CREATE TABLE IF NOT EXISTS events( aggregrateid uuid NOT NULL, type text, version int, timestamp timestamp without time zone default (now() at time zone 'utc'), data jsonb ) `); err != nil { db.Close() lgr.WithError(err).Errorf("Unable to initialize tables") return nil, ErrCouldNotCreateTables } return &PostgresEventStore{ eventBus: eventBus, db: db, factories: make(map[string]func() Event), lgr: lgr, }, nil }
// NewRabbitMQCommandBus creates a new RabbitMQ command bus. amqpURI is the RabbitMQ // URI for rabbitmq. app is provides a namespace for this application, allowing // for multiple command buses to run on one RabbitMQ and not conflict with eachother. // tag is used as the RabbitMQ consumer tag for this bus. func NewRabbitMQCommandBus(amqpURI, app, tag string) (*RabbitMQCommandBus, error) { lgr := lager.Child() connection, err := amqp.Dial(amqpURI) if err != nil { lgr.WithError(err).Errorf("Error dialing URI: %s", amqpURI) return nil, fmt.Errorf("Dial err: %s", err) } channel, err := connection.Channel() if err != nil { connection.Close() lgr.WithError(err).Errorf("Error opening channel") return nil, fmt.Errorf("Channel: %s", err) } exchange := appExchange(app, commandExchange) queueName := appTagQueueName(app, tag, commandQueueName) if err := channel.ExchangeDeclare( exchange, // name commandExchangeType, // type true, // durable false, // auto-deleted false, // internal false, // noWait nil, // arguments ); err != nil { channel.Close() connection.Close() lgr.WithError(err).Errorf("Error declaring exchange :%s", exchange) return nil, fmt.Errorf("Exchange Declare: %s", err) } queue, err := channel.QueueDeclare( queueName, // name of the queue true, // durable false, // delete when usused false, // exclusive false, // noWait nil, // arguments ) if err != nil { channel.Close() connection.Close() lgr.WithError(err).Errorf("Error declaring queue %s", queueName) return nil, fmt.Errorf("Queue Declare: %s", err) } if err = channel.QueueBind( queue.Name, // name of the queue commandKey, // bindingKey exchange, // sourceExchange false, // noWait nil, // arguments ); err != nil { channel.Close() connection.Close() lgr.WithError(err).Errorf("Error binding queue %s", queueName) return nil, fmt.Errorf("Queue Bind: %s", err) } deliveries, err := channel.Consume( queue.Name, // name tag, // consumerTag, false, // noAck false, // exclusive false, // noLocal false, // noWait nil, // arguments ) if err != nil { channel.Close() connection.Close() lgr.WithError(err).Errorf("Error consuming queue %s", queueName) return nil, fmt.Errorf("Queue Consume: %s", err) } bus := &RabbitMQCommandBus{ conn: connection, channel: channel, exchange: exchange, queue: queueName, tag: tag, handlers: make(map[string]CommandHandler), factories: make(map[string]func() Command), done: make(chan error), lgr: lgr, } go bus.handleCommands(deliveries, bus.done) return bus, nil }