简体   繁体   English

如何使 Buffalo 事务中间件提交?

[英]How to cause Buffalo transaction middleware to commit?

In trying to use the buffalo-pop/pop/popmw Transaction middleware, I am not having success writing to the database.在尝试使用 buffalo-pop/pop/popmw Transaction中间件时,我没有成功写入数据库。 No errors are returned, and the debug output shows the SQL statements, but the updates and inserts are not committed.没有返回错误,调试 output 显示 SQL 语句,但未提交更新和插入。

The handler looks like:处理程序看起来像:


func MyHandler(c buffalo.Context) error {
    tx, ok := c.Value("tx").(*pop.Connection)
    if !ok {
        return errors.New("no transaction found")
    }

    f := models.File{
        Name: "file.txt",
    }
    if err := tx.Create(&f); err != nil {
        return err
    }

    return nil
}

app.go: app.go:

func App() *buffalo.App {
...
        app.GET("/myhandler", MyHandler)
        app.Use(popmw.Transaction(models.DB))
...
}

If I use DB, _:= pop.Connect("development") for my connection, it works correctly.如果我使用DB, _:= pop.Connect("development")进行连接,它可以正常工作。 I also observed that the autoincrement value on the table changes each time this handler is hit.我还观察到,每次点击此处理程序时,表上的自动增量值都会发生变化。

In the real app, we can't call c.Render to report a response code because we are using gqlgen as the http handler.在实际应用中,我们无法调用c.Render来报告响应代码,因为我们使用gqlgen作为 http 处理程序。 It looks like this:它看起来像这样:

func GQLHandler(c buffalo.Context) error {
    h := handler.GraphQL(gqlgen.NewExecutableSchema(gqlgen.Config{Resolvers: &gqlgen.Resolver{}}))
    newCtx := context.WithValue(c.Request().Context(), "BuffaloContext", c)
    h.ServeHTTP(c.Response(), c.Request().WithContext(newCtx))

    return nil
}

One of the features of the Pop Middleware for Buffalo is to wrap the action and the middlewares below in the stack inside a DB transaction. Buffalo 的 Pop 中间件的功能之一是将操作和下面的中间件包装在数据库事务中的堆栈中。 Here are the conditions for an auto-commit from the Pop Middleware:以下是 Pop 中间件自动提交的条件:

  • Commit if there was no error executing the middlewares and action;如果执行中间件和操作没有错误,则提交; and the response status is a 2xx or 3xx.响应状态为 2xx 或 3xx。
  • Rollback otherwise.否则回滚。

From Buffalo integration with Pop .来自Buffalo 与 Pop 的整合

So, make sure no error is returned in either your action or in a middleware of the stack;因此,请确保在您的操作或堆栈的中间件中没有返回错误; and the produced response status is 200-ish or 300-ish.并且产生的响应状态是 200-ish 或 300-ish。

If Buffalo receives no response code via a call to c.Render , the Transaction middleware treats the request as non-successful.如果 Buffalo 通过调用c.Render没有收到响应代码,则 Transaction 中间件将请求视为不成功。 Since the context of this question is GraphQL using gqlgen, and c.Render cannot be used, I found that explicitly closing the transaction works.由于这个问题的上下文是 GraphQL using gqlgen,而c.Render不能使用,我发现显式关闭事务有效。 Something like this:像这样的东西:

func GQLHandler(c buffalo.Context) error {
    gqlSuccess := true
    h := handler.GraphQL(gqlgen.NewExecutableSchema(gqlgen.Config{Resolvers: &gqlgen.Resolver{}})),
        handler.ErrorPresenter(
            func(ctx context.Context, e error) *gqlerror.Error {
                gqlSuccess = false
                return graphql.DefaultErrorPresenter(ctx, e)
            }))
    newCtx := context.WithValue(c.Request().Context(), "BuffaloContext", c)
    h.ServeHTTP(c.Response(), c.Request().WithContext(newCtx))

    if !gqlSuccess {
        return nil
    }

    tx, ok := c.Value("tx").(*pop.Connection)
    if !ok {
        return errors.New("no transaction found")
    }
    return tx.TX.Commit()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM