diff --git a/entc/gen/internal/bindata.go b/entc/gen/internal/bindata.go index 00a231488..d0cb18ef6 100644 --- a/entc/gen/internal/bindata.go +++ b/entc/gen/internal/bindata.go @@ -304,7 +304,7 @@ func templateConfigTmpl() (*asset, error) { return a, nil } -var _templateContextTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\x91\x5f\x6b\xdb\x30\x14\xc5\x9f\xa3\x4f\x71\x08\x81\xd9\xc1\x53\xba\xbe\x6d\xb0\x87\x62\x5a\x28\x1b\x65\xb0\xb1\x3d\x0e\x55\xba\xb6\x45\x1c\xc9\x48\xd7\x4d\x82\xc9\x77\x1f\xf2\x9f\x35\xe4\xf5\x9e\xa3\xa3\xf3\xbb\x77\x18\x76\x5b\x51\xfa\xee\x1c\x6c\xdd\x30\xee\xef\x3e\x7d\xfe\xd8\x05\x8a\xe4\x18\x4f\x4a\xd3\xab\xf7\x7b\x3c\x3b\x2d\xf1\xd0\xb6\x18\x4d\x11\x49\x0f\x6f\x64\xa4\xf8\xd5\xd8\x88\xe8\xfb\xa0\x09\xda\x1b\x82\x8d\x68\xad\x26\x17\xc9\xa0\x77\x86\x02\xb8\x21\x3c\x74\x4a\x37\x84\x7b\x79\xb7\xa8\xa8\x7c\xef\x8c\xb0\x6e\xd4\xbf\x3f\x97\x8f\x2f\x3f\x1f\x51\xd9\x96\x30\xcf\x82\xf7\x0c\x63\x03\x69\xf6\xe1\x0c\x5f\x81\xaf\x3e\xe3\x40\x24\xc5\x76\x77\xb9\x08\x31\x0c\x30\x54\x59\x47\x58\x6b\xef\x98\x4e\xbc\xc6\x3c\xdf\x74\xfb\x1a\x5f\xbe\xe2\x55\x45\xc2\x46\x96\xde\x55\xb6\x96\x3f\x94\xde\xab\x9a\x92\x69\x18\xc0\x74\xe8\x5a\xc5\x84\x75\x43\xca\x50\x58\x63\x33\x3e\xb7\x87\xce\x07\x46\x26\x56\xff\x63\x45\x2e\x04\x9f\xbb\xc4\x3a\x0e\xbe\xd1\x19\x91\x43\xaf\x79\xb8\x08\xb1\xdb\xe1\x29\xf8\x43\x39\x69\x08\xc4\x7d\x70\x71\x84\x29\x5b\x9b\x36\x1a\xd9\x07\x32\x89\x50\x2d\x11\x05\x7c\x80\xb3\x2d\x6c\x02\xa4\x90\x56\xe8\x3e\x30\xbc\x23\x29\xaa\xde\xe9\xeb\xcc\x4c\xf3\x69\x79\x28\xe7\x59\x8e\xed\x9c\x3e\x88\x95\x2e\xf0\x37\xf1\x6a\x3e\xc9\xdf\xaa\xed\x29\x7b\x6f\x3a\x5c\x72\x99\xcd\xde\x5c\xac\xa6\x7a\xd0\x62\x6a\xfe\x42\xc7\xdb\xe2\x0a\x8e\x8e\xcb\x77\x38\x5a\x6e\x46\x96\xda\xbe\x91\x5b\x88\x14\x73\x3a\xad\x99\xbb\xbe\xa7\x64\x9d\x0a\xc9\x70\xd3\xb6\x80\x5e\xfa\xe6\xb7\x5a\x02\x58\x5a\xcd\xca\x1f\xcb\xcd\xc4\x31\xc5\x15\xb8\xe6\x29\xa0\x73\x31\x1d\x9a\x9c\x49\x47\xfb\x17\x00\x00\xff\xff\x5b\xf1\x0e\xb5\xcf\x02\x00\x00") +var _templateContextTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x93\x5d\x6b\xdb\x30\x14\x86\xaf\xab\x5f\xf1\x12\x0a\x8b\x4b\xe6\x74\xbd\xdb\x60\x17\xc5\xb4\x50\x36\xca\x60\x66\xbb\x1c\xaa\x7c\x1c\x8b\x38\x92\x91\x8f\x1b\x05\x91\xff\x3e\xe4\x8f\xe6\x63\xe4\xa6\xec\x2e\xe8\x1c\xbd\x7a\x9f\x3c\x38\x84\xe5\x8d\xc8\x6c\xb3\x73\x7a\x55\x31\xee\x6e\x3f\x7d\xfe\xd8\x38\x6a\xc9\x30\x1e\xa5\xa2\x17\x6b\xd7\x78\x32\x2a\xc5\x7d\x5d\xa3\x5f\x6a\x11\xe7\xee\x95\x8a\x54\xe4\x95\x6e\xd1\xda\xce\x29\x82\xb2\x05\x41\xb7\xa8\xb5\x22\xd3\x52\x81\xce\x14\xe4\xc0\x15\xe1\xbe\x91\xaa\x22\xdc\xa5\xb7\xd3\x14\xa5\xed\x4c\x21\xb4\xe9\xe7\xdf\x9f\xb2\x87\xe7\x9f\x0f\x28\x75\x4d\x18\xcf\x9c\xb5\x8c\x42\x3b\x52\x6c\xdd\x0e\xb6\x04\x1f\x3d\xc6\x8e\x28\x15\x37\xcb\xfd\x5e\x88\x10\x50\x50\xa9\x0d\x61\xa6\xac\x61\xf2\x3c\xc3\x78\x7e\xdd\xac\x57\xf8\xf2\x15\x2f\xb2\x25\x5c\xa7\x99\x35\xa5\x5e\xa5\x3f\xa4\x5a\xcb\x15\xc5\xa5\x10\xc0\xb4\x69\x6a\xc9\x84\x59\x45\xb2\x20\x37\xc3\x75\x7f\x5d\x6f\x1a\xeb\x18\x73\x71\xf5\x16\x2b\x12\x21\x78\xd7\x10\x54\xad\xc9\x70\xc6\xfe\x1b\xed\xd0\xb2\xeb\x14\x87\xbd\x10\xcb\x25\x1e\x9d\xdd\x64\xc3\x3a\x1c\x71\xe7\x4c\xdb\xe3\x64\xfd\x0d\xb4\x6c\x1d\x15\x91\x51\x62\x4c\x5d\xc0\x3a\x18\x5d\x43\x47\x44\x72\xf1\x4f\x34\x1f\x18\xd6\x50\x2a\xca\xce\xa8\xe3\xcc\xb9\x62\x3f\x5d\x4c\xc7\xb3\x04\x37\x63\x7a\x10\x57\x6a\x81\x3f\x91\x58\xb1\x4f\x7f\xc9\xba\xa3\xf9\x71\xd7\xb0\x4f\xd2\xf9\xb8\x9d\x88\xab\xa1\x20\x94\x18\xba\x3f\xd3\xf6\xbc\xba\x84\xa1\xed\xf4\x20\xb6\x9a\xab\x9e\x66\xa5\x5f\xc9\x4c\x4c\x92\x39\xea\x2d\xc6\xb6\x87\x94\x79\x23\x5d\x5c\x38\xeb\xbb\x80\x9a\x1a\x27\xe7\xb3\x88\x30\xb5\x1a\x27\xbf\x35\x57\x03\xc9\x10\xb7\xc0\x29\xd1\x02\x2a\x89\x00\xbd\x18\xf6\x27\x52\x30\x5a\xc9\xfd\x25\x2f\xb9\x7f\x9f\x93\x93\xc4\x0b\x56\x72\x1f\x71\xd8\xff\xa3\x64\x6a\x39\xe8\xc8\xfd\x41\x05\xfb\x83\x8b\xdc\xff\x1f\x1b\x6f\x39\x17\x7d\xb0\x8f\x65\xdf\x27\xe3\xc0\x12\x7f\xf7\x26\x42\x00\x99\x22\x7e\x44\x7f\x03\x00\x00\xff\xff\x33\x7a\xa9\x23\x5f\x04\x00\x00") func templateContextTmplBytes() ([]byte, error) { return bindataRead( @@ -319,7 +319,7 @@ func templateContextTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "template/context.tmpl", size: 719, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "template/context.tmpl", size: 1119, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1044,7 +1044,7 @@ func templateRuntimeTmpl() (*asset, error) { return a, nil } -var _templateTxTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x57\x4d\x8f\xdb\x36\x10\x3d\x4b\xbf\x62\x6a\x2c\x02\x7b\xe1\xa5\xd2\xdc\xba\xc0\x1e\x82\x4d\x0a\x04\x28\x16\x68\xe3\xa2\xb9\x25\x34\x39\xb6\x88\xc8\xa4\x4b\x8d\xbc\x32\x04\xff\xf7\x62\x48\xea\xc3\x6b\xa7\x69\x8b\x5e\xb2\x16\x39\x1f\x6f\x86\x6f\x1e\x99\xae\x2b\x6e\xf3\x47\xb7\x3f\x7a\xb3\x2d\x09\xde\xbc\xfe\xf1\xa7\xbb\xbd\xc7\x1a\x2d\xc1\xcf\x52\xe1\xda\xb9\xaf\xf0\xc1\x2a\x01\x6f\xab\x0a\x82\x51\x0d\xbc\xef\x0f\xa8\x45\xbe\x2a\x4d\x0d\xb5\x6b\xbc\x42\x50\x4e\x23\x98\x1a\x2a\xa3\xd0\xd6\xa8\xa1\xb1\x1a\x3d\x50\x89\xf0\x76\x2f\x55\x89\xf0\x46\xbc\xee\x77\x61\xe3\x1a\xab\x73\x63\xc3\xfe\x2f\x1f\x1e\xdf\x3f\x7d\x7c\x0f\x1b\x53\x21\xa4\x35\xef\x1c\x81\x36\x1e\x15\x39\x7f\x04\xb7\x01\x9a\x24\x23\x8f\x28\xf2\xdb\xe2\x74\xca\xf3\xae\x03\x8d\x1b\x63\x11\x66\xd4\xce\x20\x2d\x11\xee\xf6\x95\x24\x84\x59\x89\x52\xa3\x9f\xc1\x4d\xd8\x32\xbb\xbd\xf3\x04\xf3\x3c\x9b\x29\x67\x09\x5b\x9a\xe5\xd9\xac\x3e\x5a\x35\xcb\xf3\x6c\xb6\x35\x54\x36\x6b\xa1\xdc\xae\xd8\xa4\xfa\x8d\x55\xcd\x5a\x92\xf3\x05\x5a\x2a\xb4\x91\x15\x2a\x9a\xe5\x8b\x3c\x2f\x0a\x58\xb5\x5c\xb3\x04\xf2\xd2\xd6\x52\x91\x71\x56\x56\xa0\x2a\xc3\x1d\xa4\x52\x12\x6f\x2b\x8f\x92\x50\xc3\xfa\x08\x4a\x56\x95\xb1\x5b\x78\x0c\x16\x62\xd5\xce\x17\x22\xa7\xe3\x1e\x39\x52\x4d\xbe\x51\x04\x5d\x9e\x29\x67\x37\x66\x9b\x67\x5d\x07\x5e\xda\x2d\xc2\xcd\xe7\x25\xdc\x58\xb8\x7f\x80\x1b\xf1\xe4\x34\xd6\x70\x77\x3a\xe5\x59\x56\x14\xd0\x75\x70\x63\xc5\x93\xdc\x21\x9c\x4e\x9c\x8e\xdb\x97\x10\x6c\x9c\x07\x63\x09\x3d\x43\xb3\x5b\x78\x36\x54\x86\xfd\x73\xa7\x75\x63\x2a\x8d\xbe\x16\x79\x96\x9d\xef\xdc\x9e\x7d\x46\xd4\x01\x16\x5a\xcd\xfd\x3c\x85\x2e\x3c\xba\xdd\xce\x10\xa8\xf0\x27\x02\x98\x34\x44\xe4\x9b\xc6\x2a\x98\x53\x0b\xb7\xab\x76\x91\xac\xe7\x0b\x40\xef\x9d\xe7\x72\x3d\x52\xe3\x2d\x50\x2b\x62\xe1\x42\x7b\x73\x40\x2f\xe6\xb7\xd4\xbe\x0b\x3f\x17\x82\x5a\xd1\x3b\xa6\xac\xbf\xb9\xaa\x5a\x4b\xf5\x15\x7c\xfa\xf1\xdd\xcc\xbd\xc7\x7f\xc8\x3d\xba\xf6\x35\xc7\x0e\x47\x77\xa6\xc0\xe3\xe4\xd0\xd7\xc6\xea\x1a\xc8\x81\x6a\xbc\x0f\xab\x7f\xd3\x8e\xe0\x37\x5f\xc0\x6d\x8a\xc0\xe7\x1f\x7f\xdd\x3f\xc0\xab\xb8\xd8\x45\x70\xf7\x23\xce\x53\x6f\x25\x8c\x0d\x4d\xe9\x2b\x89\xab\x8c\xf2\x3c\x4f\x34\xe3\xe8\xdf\x61\x15\x00\x40\x46\xad\x38\x67\xc2\x03\x3c\xe1\xf3\x15\x36\xcc\x07\x44\x8b\x81\x18\x77\x91\x19\xac\x2e\xb0\x31\xbe\x26\xb0\xac\x0e\xcc\x46\xed\x14\x60\x2b\x77\xfb\x0a\x21\xcc\x6f\xd7\xdd\xc1\x4d\x34\xba\x7f\x00\x63\x35\xb6\x03\x9a\xd7\x61\x64\x8b\x02\xfa\xa3\x80\x67\x2f\xf7\xf1\x98\xb7\xe6\x80\x16\xd2\x38\x8a\x55\x1b\xb9\x2d\xc1\xba\xfd\xb0\x9a\x9c\x0c\x67\xdb\xa1\x25\x19\xfb\xcf\x73\x5b\x22\x18\x8d\x32\xcc\x8b\x83\xba\xd9\x07\x59\x98\x1c\x53\x1d\x02\xba\x86\x40\x6a\xcd\xb3\x23\xed\x11\xb0\x25\x2f\xa3\xd4\x91\x0b\x30\xc6\xd1\x29\x0a\xf8\xa3\x44\x0b\xb2\x5f\x0b\xc3\x1e\xc2\x27\x4a\xf1\xb4\x2f\xc1\x10\x6c\x31\x4d\x49\xcd\x9d\x9c\xd4\x60\x6c\x4d\xd2\x2a\x14\x93\xa9\x92\x56\x8f\x54\x97\x1e\x43\x85\xdc\x4a\x0e\x10\x86\x9b\x25\xa7\xc7\x11\xcc\x79\xa7\xa9\xd1\xc3\xae\xa9\x29\xc0\x00\x67\x91\x63\x06\x1d\xc5\x1d\xab\xac\xf3\x41\x9f\x5d\x1a\x5b\x70\x7e\x18\xa4\xcb\x39\x2a\x0a\xf6\xfe\xb0\x01\x09\xaa\x72\x2c\xef\x93\x6d\x6e\x22\xee\xd6\xa8\x35\xea\x10\xd9\x62\x4a\x04\x5b\xb4\xe8\x83\xf8\xa1\x25\x43\x06\xeb\xe5\x80\x30\xac\x1c\x39\xae\xdc\xef\x2b\x83\x3c\x44\x7f\x36\xe8\x8f\xcb\x50\x5e\x62\xc9\x7d\xd0\xaa\x40\x90\x9e\x78\xe2\x57\xb6\xfa\xf4\xe9\x13\xb7\x93\x23\x05\x2f\x78\x36\x55\x05\x6b\x04\x6c\x51\x35\x84\x3a\x10\xa7\xf4\xae\xd9\x46\xcd\xd3\x89\x42\xa5\x51\xe5\xa0\xc9\xe1\x56\xb9\x52\xea\x93\x23\x8c\xb3\x3c\x70\xcf\xd4\x60\x1d\xc1\xd6\x79\xd7\x10\xdf\x37\xb5\xdc\x60\x52\xef\xc1\x68\xd4\xf0\x90\x7d\xcc\x8a\x50\x93\xf4\x31\xe5\x59\x73\x61\xe3\xdd\x4e\xe4\x99\xf6\x87\x17\xc4\x8d\x31\xda\x5e\xd3\xc3\x85\x5a\x1d\x99\x8b\x67\x80\x33\x6a\x27\x1c\x4a\xf2\x64\xf1\x79\xd5\xa6\x2a\xb9\xb1\x16\x9f\x5f\x5c\x52\x89\x94\x51\x25\x82\xf9\x5c\x51\x0b\xe9\x56\x14\x8f\xf1\xef\x12\x2e\x71\x2d\x60\x14\xc7\x65\x54\xd2\xa0\x2b\xd4\x86\x2f\x9e\x63\xed\x0f\x22\x06\x5c\xe4\x99\xd9\x84\xe5\x1f\x1e\xc0\x9a\x8a\x0d\x7b\xa9\xb2\xa6\x0a\x1e\x79\x76\x1a\xe4\xeb\x55\x1f\xb9\xa3\x96\xe5\x2e\x00\xb8\xe7\x7f\x4e\x4b\x76\x48\xf5\xad\xda\x41\x7a\x5f\xf6\x93\x35\x62\x8f\x9e\x95\xaf\xc7\x4b\x0e\xe4\xc1\x19\xdd\xcf\x94\xf3\xe3\x48\x85\x29\xe5\x90\x7c\x0e\xd7\x87\x4a\xc0\xc7\xd2\x35\x95\x66\x76\xb1\x39\x6a\x70\xb6\x3a\xf2\x85\x7e\xdd\x7e\x22\xbd\x23\x08\xee\xc7\x79\x73\x17\x30\x1f\x0f\x6e\xec\x24\x0c\x77\x52\xa8\x18\x62\xc5\xef\xa2\xe5\x59\xd9\xc9\xbb\x9f\xb6\x7f\xca\xb5\x6b\xe8\x52\xf8\xf9\x82\x29\xcc\x1c\x9b\xc0\x10\x7c\x9c\xa3\x41\x7f\x01\xba\x1a\xe3\xeb\x87\x15\x29\xc8\x42\x1f\x7a\x12\x37\x98\x8d\x17\x2e\x8c\x47\x0f\x67\x8f\x87\x31\x50\xfc\xfe\xa6\xc2\x05\x6d\xfc\xfd\x5c\xdd\xbe\xac\xfa\xd7\xc1\x97\x6b\xd2\xf6\x8d\x67\xc1\x14\xe5\x8b\x37\xc9\x25\xcc\x81\x2f\x03\xd0\x41\x2d\xff\x35\xd4\x3e\xd6\x39\xd8\x6f\xab\xef\x05\xdc\xcb\x87\xcc\x25\xe0\xf7\x2d\xaa\xfe\x0a\x6a\x05\x7f\x5d\x3f\x78\xde\xb9\x3e\xf9\x51\x56\x23\x1d\x96\x20\xfd\xb6\x5e\xc2\x21\x56\xc9\x8f\xe3\xee\x74\xf5\x19\x95\x92\x71\xc8\x65\xaf\xe7\xc9\xb7\x7f\x3b\x05\xfd\x1e\xb1\x85\xcf\xeb\xe0\xc2\xd6\xff\x8c\x6e\x88\x79\x15\xde\x41\x7a\xf8\xfc\xf2\x05\xf1\x30\xed\xfe\xdc\x9a\x6a\x11\xfe\x93\x91\x1e\xc1\x7f\x05\x00\x00\xff\xff\x73\xc6\x54\xa9\x46\x0d\x00\x00") +var _templateTxTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x57\x5f\x8b\xdb\x48\x12\x7f\x96\x3e\x45\x9d\x19\x82\x35\x38\x52\x2e\x6f\x37\x30\x0f\x61\x92\x40\x20\x37\xc7\x5d\x1c\x2e\x70\x1c\x49\x5b\x5d\xb2\x9b\xc8\xdd\xda\x56\xc9\x23\x63\xfc\xdd\x97\xaa\x6e\x59\xf2\xd8\xc9\x66\x61\xf3\x90\x51\x77\x55\xff\xba\xfe\xfe\xaa\x7d\x38\x14\xb7\xe9\x83\x6b\xf6\xde\xac\x37\x04\xaf\x5f\xfd\xfd\x1f\x2f\x1b\x8f\x2d\x5a\x82\xf7\xaa\xc4\x95\x73\xdf\xe1\x83\x2d\x73\x78\x53\xd7\x20\x4a\x2d\xb0\xdc\xef\x50\xe7\xe9\x72\x63\x5a\x68\x5d\xe7\x4b\x84\xd2\x69\x04\xd3\x42\x6d\x4a\xb4\x2d\x6a\xe8\xac\x46\x0f\xb4\x41\x78\xd3\xa8\x72\x83\xf0\x3a\x7f\x35\x48\xa1\x72\x9d\xd5\xa9\xb1\x22\xff\xf8\xe1\xe1\xdd\xe3\xa7\x77\x50\x99\x1a\x21\xee\x79\xe7\x08\xb4\xf1\x58\x92\xf3\x7b\x70\x15\xd0\xe4\x32\xf2\x88\x79\x7a\x5b\x1c\x8f\x69\x7a\x38\x80\xc6\xca\x58\x84\x19\xf5\x33\x88\x5b\x84\xdb\xa6\x56\x84\x30\xdb\xa0\xd2\xe8\x67\x70\x23\x22\xb3\x6d\x9c\x27\x98\xa7\xc9\xac\x74\x96\xb0\xa7\x59\x9a\xcc\xda\xbd\x2d\x67\x69\x9a\xcc\xd6\x86\x36\xdd\x2a\x2f\xdd\xb6\xa8\xa2\xff\xc6\x96\xdd\x4a\x91\xf3\x05\x5a\x2a\xb4\x51\x35\x96\x34\x4b\xb3\x34\x2d\x0a\x58\xf6\xec\xb3\x02\xf2\xca\xb6\xaa\x24\xe3\xac\xaa\xa1\xac\x0d\x47\x90\x36\x8a\x58\x5c\x7a\x54\x84\x1a\x56\x7b\x28\x55\x5d\x1b\xbb\x86\x07\xd1\xc8\x97\xfd\x3c\xcb\x53\xda\x37\xc8\x48\x2d\xf9\xae\x24\x38\xa4\x49\xe9\x6c\x65\xd6\x69\x72\x38\x80\x57\x76\x8d\x70\xf3\x75\x01\x37\x16\xee\xee\xe1\x26\x7f\x74\x1a\x5b\x78\x79\x3c\xa6\x49\x52\x14\x70\x38\xc0\x8d\xcd\x1f\xd5\x16\xe1\x78\xe4\xeb\x38\x7c\xd1\x82\xca\x79\x30\x96\xd0\xb3\x69\x76\x0d\x4f\x86\x36\x22\x3f\x3f\xb4\xea\x4c\xad\xd1\xb7\x79\x9a\x24\xe7\x92\xdb\xb3\x65\xb0\x5a\xcc\x42\xab\x25\x9e\x6c\x41\xe9\xb6\x4d\x8d\xec\xbb\xf8\xb7\x52\xe5\x77\x86\xda\x76\x30\xfc\xe3\xf8\xe6\xff\xec\x08\xfb\x34\x71\xf6\xc1\x6d\xb7\x86\x00\xe0\x7f\xff\xaf\x3a\x5b\xce\xd1\x7b\xe7\x33\x96\xfc\xc7\x85\xe3\xcf\x24\x92\xd2\x97\x43\x28\x58\xc2\x91\xa8\x4d\x4b\x30\x0b\x60\x33\x98\x0d\x67\xa5\x04\x12\xd6\xbf\x71\xf6\x7d\x67\xcb\x96\x95\x1b\x6f\x2c\xc1\xcc\xd9\x59\x04\x60\xa5\x18\xbd\xb8\xe6\xef\xda\x3d\xa1\x3f\xed\x84\x58\x4e\x72\x9b\xa7\x89\x88\xe6\xd4\xc3\xed\xb2\xcf\xa6\xc7\xe7\x19\x88\xb9\x9c\xbf\x04\xbd\xe7\x5b\xa9\xcf\x43\x2a\x73\xed\xcd\x0e\x7d\x3e\xbf\xa5\xfe\xad\x7c\x66\x39\xf5\xf9\xd9\xf1\x34\x49\xa8\xcf\xb7\x5d\xfe\xd1\x95\xdf\x65\xa9\xb1\xe2\x16\x92\xcd\xcf\xb6\x1e\xb6\x39\xab\x5f\x17\x50\xf1\x0d\x21\x26\x11\x6a\xf0\x97\x7d\x49\x93\x24\xa9\x38\x80\x7c\x82\x4b\xc5\x23\x75\xde\xb2\x8d\x69\x12\x13\xf7\x2f\x3b\x75\x5f\x69\xcd\xa5\xcc\x4b\xc9\x25\x39\x49\x27\x38\x7b\x19\x99\x8b\x40\x9c\x41\xcd\x2b\x98\xa4\x2f\x13\x63\x7e\xcd\xb5\x4b\x47\xee\x41\x35\x0d\x5a\x3d\xbf\x10\x2d\xa0\xca\xd8\x15\x4e\xf5\x50\x8e\x45\x11\x5b\x0b\x82\xbb\xec\xd0\xc3\xa4\x1b\x57\xc6\xea\x56\x3c\xeb\xbc\x97\xdd\x69\x72\xcf\x5d\x0a\xe7\xe6\x19\xdc\x46\x04\x6e\xcc\xf0\x75\x77\x0f\x2f\xc2\xe6\x21\xe4\xf7\x6e\x4c\xf5\x71\xd0\xca\x8d\x35\xc4\x5e\xc5\xc8\x87\x5d\x2e\xe6\xf3\x7b\x82\x1a\xa3\xff\x41\xbb\x73\x27\x0d\x11\x1a\x5b\xf4\x1e\x1e\xf1\xe9\x4a\x9b\xce\x4f\x16\x65\xa7\x8e\x65\x14\x69\xa6\xe2\x16\x2a\xe3\x5b\x02\xcb\xb4\xcd\x05\xa5\x5d\x09\xd8\x2b\xee\x64\x10\x62\x95\x0e\x0a\x4a\x77\xf7\x60\xac\xc6\xfe\x64\xcd\xab\x21\xd8\x43\x35\xc3\x93\x57\x4d\x68\x97\xb5\xd9\xa1\x85\xc8\x93\xf9\xb2\x0f\xa4\xa3\xc0\xba\xe6\xb4\x1b\x0f\x19\xbe\x6d\x8b\x96\x54\x88\x3f\x13\xea\x06\xc1\x68\x54\x42\x64\x0e\xda\xae\x11\xbe\x9e\xa4\xa9\x15\x40\xd7\x11\x17\x2c\x93\x9a\xb2\x7b\xc0\x9e\xbc\x0a\x33\x88\x9c\x98\x31\x72\x5a\x51\xc0\x7f\x37\x68\x41\x0d\x7b\x52\xd6\x02\x1f\xbb\x92\x69\x78\x01\x86\x60\x8d\x14\x9c\x68\x39\x92\x13\x1f\x8c\x6d\x49\xd9\x12\x05\x2d\xf2\x97\xb2\x1a\x4e\x84\xa5\x3c\x8a\x87\x1c\x4a\x06\x10\xd6\xe5\x59\x30\xd8\x21\xea\x2c\xe9\x5a\xf4\xb0\xed\x5a\x1a\xba\x0b\x19\x53\x06\x1c\x6e\x79\xfc\x39\x2f\x83\xd3\x31\xaf\xf2\x3d\xce\x83\x1f\xae\xb9\xe0\xa3\xa2\xe0\xd3\x1f\x2a\x50\x50\xd6\x8e\xe7\xee\x44\xcc\x41\xc4\xed\x0a\xb5\x46\x2d\xc8\x16\xe3\x45\xb0\x46\x8b\x5e\xa6\x12\x5a\x32\x64\xb0\x5d\x9c\x2c\x94\x9d\x3d\xe3\xaa\xa6\xa9\x0d\x72\x13\xfd\xd6\xa1\xdf\x2f\xc4\xbd\x58\x25\x77\x81\xfc\xb8\x40\x86\xc2\xcb\xff\xcd\x5a\x5f\xbe\x7c\xe1\x70\x32\x92\x9c\x82\x27\x53\xd7\xb0\x42\xc0\x1e\xcb\x8e\x50\x4b\xe1\x6c\xbc\xeb\xd6\x61\x18\xe9\x58\x42\x1b\x53\x6e\x4e\xc3\x52\xc6\xfd\x15\x57\x1f\x1d\x61\xe8\xe5\x53\xed\x99\x16\xac\x23\x58\x3b\xef\x3a\xe2\x87\x40\xab\x2a\x8c\x63\xf5\xa4\x34\x0e\x57\xb9\x7d\xbc\x15\xa1\x25\xe5\xc3\x95\x67\xc1\x85\xca\xbb\x6d\x9e\x26\xda\xef\x9e\x15\x6e\xc0\xe8\x87\x61\x2b\x2f\x9d\x7a\xcf\xb5\x78\x3e\x2b\xa8\x9f\xd4\x50\x1a\x3a\xc6\xe2\xd3\xb2\x8f\x5e\x72\x60\x2d\x3e\x3d\x7b\x3d\xc4\xa2\x0c\x2c\x21\xea\xf3\x92\x7a\x88\xcf\x95\xfc\x21\xfc\x5d\xc0\xa5\x5d\x19\x8c\xf3\x65\x11\xa6\x91\xf0\x0a\xf5\xb2\xe2\x3e\xd6\x7e\x97\x07\xc0\x2c\x4d\x4c\x25\xdb\x7f\xbb\x07\x6b\x6a\x61\xe9\x48\x55\xd6\xd4\x8b\x61\x52\x0c\x7b\x2f\x06\xe4\x03\xf5\x4c\x77\x62\xc0\x1d\xff\x77\x5c\xf0\x81\xe8\xdf\xb2\x3f\x51\xef\xf3\x78\x32\x47\x34\xe8\x99\xf9\x06\x7b\xc9\x81\xda\x39\xa3\x87\x9e\x72\x7e\x6c\x29\xe9\x52\x86\xe4\x3c\x5c\x6f\xaa\x1c\x3e\x6d\x5c\x57\x6b\xae\x2e\x56\x47\x0d\xce\xd6\x7b\x7e\x69\x5d\xd7\x9f\x50\xef\x68\x04\xc7\xe3\x3c\xb8\x19\xcc\xc7\xc4\x8d\x91\x8c\x9e\x89\xf3\x1c\xb1\xe0\xf1\xdb\xa0\x79\xe6\x76\x3c\x3d\x74\xdb\xaf\xd6\xda\x35\xeb\x22\xfc\x3c\xe3\x12\xe6\x1a\x9b\x98\x91\x73\x3a\x47\x85\x61\x00\xba\x16\xc3\xb3\x94\x19\x49\x68\x61\x80\x9e\xe0\x8a\xda\xf8\x68\x81\x31\xf5\x03\x4e\x48\xc9\x08\x14\xd6\x3f\x64\x38\xe1\xc6\xcf\xe7\xec\xf6\x6d\xd9\xe7\x01\xe7\xdb\x35\x6a\xbb\xa0\xb3\x4b\x2b\x45\xf1\x67\x66\x9e\xea\xe5\x64\xe8\x89\x2d\xff\xb4\xa9\x03\xd6\xb9\xb1\x3f\x66\xdf\x0b\x73\x07\x80\x9f\x19\xfc\xae\xc7\x72\x18\x41\x7d\xce\xab\xeb\x89\x67\xc9\xf5\xce\x0f\xb4\x1a\xca\x61\x01\xca\xaf\xdb\x05\xec\x82\x97\xfc\xab\xe5\x70\x9c\x3c\x45\xc7\x5a\x89\x97\x31\xe4\x62\xe0\xf3\x78\x36\x8b\xcd\x2b\xfc\x3d\xda\x26\xcb\xeb\xc6\x89\xe8\x2f\xb6\xee\x84\x79\xd5\xbc\x9d\xf2\xf0\xf5\xf9\x0b\xe2\x7e\x1a\xfd\xb9\x35\x75\x26\xbf\xfe\xe2\x73\xf0\xf7\x00\x00\x00\xff\xff\x2f\xa8\x3f\x7e\xdf\x0e\x00\x00") func templateTxTmplBytes() ([]byte, error) { return bindataRead( @@ -1059,7 +1059,7 @@ func templateTxTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "template/tx.tmpl", size: 3398, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "template/tx.tmpl", size: 3807, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/entc/gen/template/context.tmpl b/entc/gen/template/context.tmpl index 79255ec4e..1fd4cf835 100644 --- a/entc/gen/template/context.tmpl +++ b/entc/gen/template/context.tmpl @@ -13,17 +13,30 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct {} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } {{ end }} diff --git a/entc/gen/template/tx.tmpl b/entc/gen/template/tx.tmpl index 70294b033..763ff5638 100644 --- a/entc/gen/template/tx.tmpl +++ b/entc/gen/template/tx.tmpl @@ -22,17 +22,33 @@ type Tx struct { // {{ $n.Name }} is the client for interacting with the {{ $n.Name }} builders. {{ $n.Name }} *{{ $n.Name }}Client {{ end }} + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } -// Commit commits the transaction. -func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() -} +{{- range $func := list "Commit" "Rollback" }} + {{- $onFuncs := print "on" $func }} + // {{ $func }} {{ lower $func }}s the transaction. + func (tx *Tx) {{ $func }}() error { + err := tx.config.driver.(*txDriver).tx.{{ $func }}() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.{{ $onFuncs }} { + f(err) + } + return err + } -// Rollback rollbacks the transaction. -func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() -} + // On{{ $func }} adds a function to call on {{ lower $func }}. + func (tx *Tx) On{{ $func }}(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.{{ $onFuncs }} = append(tx.{{ $onFuncs }}, f) + } +{{- end }} // Client returns a Client that binds to current transaction. func (tx *Tx) Client() *Client { diff --git a/entc/integration/config/ent/context.go b/entc/integration/config/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/entc/integration/config/ent/context.go +++ b/entc/integration/config/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/entc/integration/config/ent/tx.go b/entc/integration/config/ent/tx.go index fe30afd5c..5271bf78d 100644 --- a/entc/integration/config/ent/tx.go +++ b/entc/integration/config/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -17,16 +18,47 @@ type Tx struct { config // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/entc/integration/customid/ent/context.go b/entc/integration/customid/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/entc/integration/customid/ent/context.go +++ b/entc/integration/customid/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/entc/integration/customid/ent/tx.go b/entc/integration/customid/ent/tx.go index bfac47915..4d68e384d 100644 --- a/entc/integration/customid/ent/tx.go +++ b/entc/integration/customid/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -25,16 +26,47 @@ type Tx struct { Pet *PetClient // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/entc/integration/ent/context.go b/entc/integration/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/entc/integration/ent/context.go +++ b/entc/integration/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/entc/integration/ent/tx.go b/entc/integration/ent/tx.go index bf9096fd5..a05d68bdf 100644 --- a/entc/integration/ent/tx.go +++ b/entc/integration/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -39,16 +40,47 @@ type Tx struct { Spec *SpecClient // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/entc/integration/gremlin/ent/context.go b/entc/integration/gremlin/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/entc/integration/gremlin/ent/context.go +++ b/entc/integration/gremlin/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/entc/integration/gremlin/ent/tx.go b/entc/integration/gremlin/ent/tx.go index bf9096fd5..a05d68bdf 100644 --- a/entc/integration/gremlin/ent/tx.go +++ b/entc/integration/gremlin/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -39,16 +40,47 @@ type Tx struct { Spec *SpecClient // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/entc/integration/hooks/ent/context.go b/entc/integration/hooks/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/entc/integration/hooks/ent/context.go +++ b/entc/integration/hooks/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/entc/integration/hooks/ent/tx.go b/entc/integration/hooks/ent/tx.go index f671a76d1..990470f46 100644 --- a/entc/integration/hooks/ent/tx.go +++ b/entc/integration/hooks/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -19,16 +20,47 @@ type Tx struct { Card *CardClient // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/entc/integration/idtype/ent/context.go b/entc/integration/idtype/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/entc/integration/idtype/ent/context.go +++ b/entc/integration/idtype/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/entc/integration/idtype/ent/tx.go b/entc/integration/idtype/ent/tx.go index fe30afd5c..5271bf78d 100644 --- a/entc/integration/idtype/ent/tx.go +++ b/entc/integration/idtype/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -17,16 +18,47 @@ type Tx struct { config // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/entc/integration/integration_test.go b/entc/integration/integration_test.go index 1511255b8..413705038 100644 --- a/entc/integration/integration_test.go +++ b/entc/integration/integration_test.go @@ -27,6 +27,7 @@ import ( "github.com/facebookincubator/ent/entc/integration/ent/node" "github.com/facebookincubator/ent/entc/integration/ent/pet" "github.com/facebookincubator/ent/entc/integration/ent/user" + "github.com/stretchr/testify/mock" "github.com/go-sql-driver/mysql" _ "github.com/lib/pq" @@ -788,34 +789,50 @@ func UniqueConstraint(t *testing.T, client *ent.Client) { require.Error(err) } +type mocker struct{ mock.Mock } + +func (m *mocker) onCommit(err error) { m.Called(err) } +func (m *mocker) onRollback(err error) { m.Called(err) } + func Tx(t *testing.T, client *ent.Client) { ctx := context.Background() - require := require.New(t) - - tx, err := client.Tx(ctx) - require.NoError(err) - tx.Node.Create().SaveX(ctx) - - require.NoError(tx.Rollback()) - require.Zero(client.Node.Query().CountX(ctx), "rollback should discard all changes") - - tx, err = client.Tx(ctx) - require.NoError(err) - - nde := tx.Node.Create().SaveX(ctx) - - require.NoError(tx.Commit()) - require.Error(tx.Commit(), "should return an error on the second call") - require.NotZero(client.Node.Query().CountX(ctx), "commit should save all changes") - _, err = nde.QueryNext().Count(ctx) - require.Error(err, "should not be able to query after tx was closed") - require.Zero(nde.Unwrap().QueryNext().CountX(ctx), "should be able to query the entity after wrap") - - tx, err = client.Tx(ctx) - require.NoError(err) - _, err = tx.Client().Tx(ctx) - require.Error(err, "cannot start a transaction within a transaction") - require.NoError(tx.Rollback()) + t.Run("Rollback", func(t *testing.T) { + tx, err := client.Tx(ctx) + require.NoError(t, err) + var m mocker + m.On("onRollback", nil).Once() + defer m.AssertExpectations(t) + tx.OnRollback(m.onRollback) + tx.Node.Create().SaveX(ctx) + require.NoError(t, tx.Rollback()) + require.Zero(t, client.Node.Query().CountX(ctx), "rollback should discard all changes") + }) + t.Run("Commit", func(t *testing.T) { + tx, err := client.Tx(ctx) + require.NoError(t, err) + var m mocker + m.On("onCommit", mock.Anything).Twice() + defer m.AssertExpectations(t) + tx.OnCommit(m.onCommit) + nde := tx.Node.Create().SaveX(ctx) + require.NoError(t, tx.Commit()) + require.Error(t, tx.Commit(), "should return an error on the second call") + require.NotZero(t, client.Node.Query().CountX(ctx), "commit should save all changes") + _, err = nde.QueryNext().Count(ctx) + require.Error(t, err, "should not be able to query after tx was closed") + require.Zero(t, nde.Unwrap().QueryNext().CountX(ctx), "should be able to query the entity after wrap") + }) + t.Run("Nested", func(t *testing.T) { + tx, err := client.Tx(ctx) + require.NoError(t, err) + var m mocker + m.On("onRollback", nil).Once() + defer m.AssertExpectations(t) + tx.OnRollback(m.onRollback) + _, err = tx.Client().Tx(ctx) + require.Error(t, err, "cannot start a transaction within a transaction") + require.NoError(t, tx.Rollback()) + }) } func DefaultValue(t *testing.T, client *ent.Client) { diff --git a/entc/integration/json/ent/context.go b/entc/integration/json/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/entc/integration/json/ent/context.go +++ b/entc/integration/json/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/entc/integration/json/ent/tx.go b/entc/integration/json/ent/tx.go index fe30afd5c..5271bf78d 100644 --- a/entc/integration/json/ent/tx.go +++ b/entc/integration/json/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -17,16 +18,47 @@ type Tx struct { config // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/entc/integration/migrate/entv1/context.go b/entc/integration/migrate/entv1/context.go index 76b6d6753..276b4eae7 100644 --- a/entc/integration/migrate/entv1/context.go +++ b/entc/integration/migrate/entv1/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/entc/integration/migrate/entv1/tx.go b/entc/integration/migrate/entv1/tx.go index f08b6275b..755abced7 100644 --- a/entc/integration/migrate/entv1/tx.go +++ b/entc/integration/migrate/entv1/tx.go @@ -8,6 +8,7 @@ package entv1 import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -19,16 +20,47 @@ type Tx struct { Car *CarClient // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/entc/integration/migrate/entv2/context.go b/entc/integration/migrate/entv2/context.go index b133f5c21..820537b14 100644 --- a/entc/integration/migrate/entv2/context.go +++ b/entc/integration/migrate/entv2/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/entc/integration/migrate/entv2/tx.go b/entc/integration/migrate/entv2/tx.go index 966c4f6ef..69e97e711 100644 --- a/entc/integration/migrate/entv2/tx.go +++ b/entc/integration/migrate/entv2/tx.go @@ -8,6 +8,7 @@ package entv2 import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -23,16 +24,47 @@ type Tx struct { Pet *PetClient // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/entc/integration/privacy/ent/context.go b/entc/integration/privacy/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/entc/integration/privacy/ent/context.go +++ b/entc/integration/privacy/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/entc/integration/privacy/ent/tx.go b/entc/integration/privacy/ent/tx.go index d0c39e7ce..31f85e2ac 100644 --- a/entc/integration/privacy/ent/tx.go +++ b/entc/integration/privacy/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -19,16 +20,47 @@ type Tx struct { Galaxy *GalaxyClient // Planet is the client for interacting with the Planet builders. Planet *PlanetClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/entc/integration/template/ent/context.go b/entc/integration/template/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/entc/integration/template/ent/context.go +++ b/entc/integration/template/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/entc/integration/template/ent/tx.go b/entc/integration/template/ent/tx.go index 52cc9304d..4b6b65f12 100644 --- a/entc/integration/template/ent/tx.go +++ b/entc/integration/template/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -21,16 +22,47 @@ type Tx struct { Pet *PetClient // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/examples/edgeindex/ent/context.go b/examples/edgeindex/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/examples/edgeindex/ent/context.go +++ b/examples/edgeindex/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/examples/edgeindex/ent/tx.go b/examples/edgeindex/ent/tx.go index 1997d6b27..c7cc2234e 100644 --- a/examples/edgeindex/ent/tx.go +++ b/examples/edgeindex/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -19,16 +20,47 @@ type Tx struct { City *CityClient // Street is the client for interacting with the Street builders. Street *StreetClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/examples/entcpkg/ent/context.go b/examples/entcpkg/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/examples/entcpkg/ent/context.go +++ b/examples/entcpkg/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/examples/entcpkg/ent/tx.go b/examples/entcpkg/ent/tx.go index fe30afd5c..5271bf78d 100644 --- a/examples/entcpkg/ent/tx.go +++ b/examples/entcpkg/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -17,16 +18,47 @@ type Tx struct { config // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/examples/m2m2types/ent/context.go b/examples/m2m2types/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/examples/m2m2types/ent/context.go +++ b/examples/m2m2types/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/examples/m2m2types/ent/tx.go b/examples/m2m2types/ent/tx.go index d8af1c483..dbaca2990 100644 --- a/examples/m2m2types/ent/tx.go +++ b/examples/m2m2types/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -19,16 +20,47 @@ type Tx struct { Group *GroupClient // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/examples/m2mbidi/ent/context.go b/examples/m2mbidi/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/examples/m2mbidi/ent/context.go +++ b/examples/m2mbidi/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/examples/m2mbidi/ent/tx.go b/examples/m2mbidi/ent/tx.go index fe30afd5c..5271bf78d 100644 --- a/examples/m2mbidi/ent/tx.go +++ b/examples/m2mbidi/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -17,16 +18,47 @@ type Tx struct { config // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/examples/m2mrecur/ent/context.go b/examples/m2mrecur/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/examples/m2mrecur/ent/context.go +++ b/examples/m2mrecur/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/examples/m2mrecur/ent/tx.go b/examples/m2mrecur/ent/tx.go index fe30afd5c..5271bf78d 100644 --- a/examples/m2mrecur/ent/tx.go +++ b/examples/m2mrecur/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -17,16 +18,47 @@ type Tx struct { config // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/examples/o2m2types/ent/context.go b/examples/o2m2types/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/examples/o2m2types/ent/context.go +++ b/examples/o2m2types/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/examples/o2m2types/ent/tx.go b/examples/o2m2types/ent/tx.go index 7a11242bc..f20b01880 100644 --- a/examples/o2m2types/ent/tx.go +++ b/examples/o2m2types/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -19,16 +20,47 @@ type Tx struct { Pet *PetClient // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/examples/o2mrecur/ent/context.go b/examples/o2mrecur/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/examples/o2mrecur/ent/context.go +++ b/examples/o2mrecur/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/examples/o2mrecur/ent/tx.go b/examples/o2mrecur/ent/tx.go index ea811ee19..b7db6a3ea 100644 --- a/examples/o2mrecur/ent/tx.go +++ b/examples/o2mrecur/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -17,16 +18,47 @@ type Tx struct { config // Node is the client for interacting with the Node builders. Node *NodeClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/examples/o2o2types/ent/context.go b/examples/o2o2types/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/examples/o2o2types/ent/context.go +++ b/examples/o2o2types/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/examples/o2o2types/ent/tx.go b/examples/o2o2types/ent/tx.go index f671a76d1..990470f46 100644 --- a/examples/o2o2types/ent/tx.go +++ b/examples/o2o2types/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -19,16 +20,47 @@ type Tx struct { Card *CardClient // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/examples/o2obidi/ent/context.go b/examples/o2obidi/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/examples/o2obidi/ent/context.go +++ b/examples/o2obidi/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/examples/o2obidi/ent/tx.go b/examples/o2obidi/ent/tx.go index fe30afd5c..5271bf78d 100644 --- a/examples/o2obidi/ent/tx.go +++ b/examples/o2obidi/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -17,16 +18,47 @@ type Tx struct { config // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/examples/o2orecur/ent/context.go b/examples/o2orecur/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/examples/o2orecur/ent/context.go +++ b/examples/o2orecur/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/examples/o2orecur/ent/tx.go b/examples/o2orecur/ent/tx.go index ea811ee19..b7db6a3ea 100644 --- a/examples/o2orecur/ent/tx.go +++ b/examples/o2orecur/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -17,16 +18,47 @@ type Tx struct { config // Node is the client for interacting with the Node builders. Node *NodeClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/examples/start/ent/context.go b/examples/start/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/examples/start/ent/context.go +++ b/examples/start/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/examples/start/ent/tx.go b/examples/start/ent/tx.go index 1c52d9aa9..2b5b0b4c0 100644 --- a/examples/start/ent/tx.go +++ b/examples/start/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -21,16 +22,47 @@ type Tx struct { Group *GroupClient // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction. diff --git a/examples/traversal/ent/context.go b/examples/traversal/ent/context.go index 57ecd33b3..08c8fa210 100644 --- a/examples/traversal/ent/context.go +++ b/examples/traversal/ent/context.go @@ -10,15 +10,28 @@ import ( "context" ) -type contextKey struct{} +type clientCtxKey struct{} // FromContext returns the Client stored in a context, or nil if there isn't one. func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(contextKey{}).(*Client) + c, _ := ctx.Value(clientCtxKey{}).(*Client) return c } // NewContext returns a new context with the given Client attached. func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, contextKey{}, c) + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns the Tx stored in a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Client attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) } diff --git a/examples/traversal/ent/tx.go b/examples/traversal/ent/tx.go index 52cc9304d..4b6b65f12 100644 --- a/examples/traversal/ent/tx.go +++ b/examples/traversal/ent/tx.go @@ -8,6 +8,7 @@ package ent import ( "context" + "sync" "github.com/facebookincubator/ent/dialect" ) @@ -21,16 +22,47 @@ type Tx struct { Pet *PetClient // User is the client for interacting with the User builders. User *UserClient + + // completion callbacks. + mu sync.Mutex + onCommit []func(error) + onRollback []func(error) } // Commit commits the transaction. func (tx *Tx) Commit() error { - return tx.config.driver.(*txDriver).tx.Commit() + err := tx.config.driver.(*txDriver).tx.Commit() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onCommit { + f(err) + } + return err +} + +// OnCommit adds a function to call on commit. +func (tx *Tx) OnCommit(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) } // Rollback rollbacks the transaction. func (tx *Tx) Rollback() error { - return tx.config.driver.(*txDriver).tx.Rollback() + err := tx.config.driver.(*txDriver).tx.Rollback() + tx.mu.Lock() + defer tx.mu.Unlock() + for _, f := range tx.onRollback { + f(err) + } + return err +} + +// OnRollback adds a function to call on rollback. +func (tx *Tx) OnRollback(f func(error)) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) } // Client returns a Client that binds to current transaction.