lolopinto / ent Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
% tsent codegen
panic: invalid foreign key table RequestOutcomeConfig
goroutine 1 [running]:
github.com/lolopinto/ent/internal/schema.NodeMapInfo.processConstraints(0xc0001312f0, 0xc000165dc0)
/Users/ola/code/ent/internal/schema/node_map.go:542 +0xce5
github.com/lolopinto/ent/internal/schema.NodeMapInfo.buildPostRunDepgraph.func5(0xc000165dc0)
/Users/ola/code/ent/internal/schema/node_map.go:126 +0x34
github.com/lolopinto/ent/internal/schema.NodeMapInfo.processDepgrah.func1(0x15eb6a0, 0xc00013d730)
/Users/ola/code/ent/internal/schema/node_map.go:146 +0x4c
github.com/lolopinto/ent/internal/depgraph.(*Depgraph).Run(0xc000165d40, 0xc0001ada40)
/Users/ola/code/ent/internal/depgraph/depgraph.go:45 +0x1b4
github.com/lolopinto/ent/internal/schema.NodeMapInfo.processDepgrah(0xc0001312f0, 0xc000168240, 0xc0003c1310, 0xf, 0xc00016d5d0)
/Users/ola/code/ent/internal/schema/node_map.go:141 +0xdb
github.com/lolopinto/ent/internal/schema.NodeMapInfo.parseInputSchema(0xc0001312f0, 0xc000163310, 0xc0000a28d0, 0x16dae88, 0xa, 0x100f8dd, 0x16a5220, 0xc000131320)
/Users/ola/code/ent/internal/schema/node_map.go:763 +0x6ef
github.com/lolopinto/ent/internal/schema.ParseFromInputSchema.func1(0xc000163310, 0xc000163310, 0x16d1471, 0x3)
/Users/ola/code/ent/internal/schema/schema.go:186 +0x4e
github.com/lolopinto/ent/internal/schema.parse(0xc0001adca0, 0x16f5cd1, 0x17, 0xc0001cc500)
/Users/ola/code/ent/internal/schema/schema.go:193 +0x87
github.com/lolopinto/ent/internal/schema.ParseFromInputSchema(0xc0000a28d0, 0x16dae88, 0xa, 0xc0000a28d0, 0x0, 0x0)
/Users/ola/code/ent/internal/schema/schema.go:185 +0x62
github.com/lolopinto/ent/tsent/cmd.glob..func1(0x1c09c00, 0x1c3b840, 0x0, 0x0, 0x0, 0x0)
/Users/ola/code/ent/tsent/cmd/codegen.go:39 +0x87
github.com/spf13/cobra.(*Command).execute(0x1c09c00, 0x1c3b840, 0x0, 0x0, 0x1c09c00, 0x1c3b840)
/Users/ola/code/gocode/pkg/mod/github.com/spf13/[email protected]/command.go:826 +0x453
github.com/spf13/cobra.(*Command).ExecuteC(0x1c0a100, 0x104386a, 0x1bcc540, 0xc000000180)
/Users/ola/code/gocode/pkg/mod/github.com/spf13/[email protected]/command.go:914 +0x2fb
github.com/spf13/cobra.(*Command).Execute(...)
/Users/ola/code/gocode/pkg/mod/github.com/spf13/[email protected]/command.go:864
github.com/lolopinto/ent/tsent/cmd.Execute()
/Users/ola/code/ent/tsent/cmd/root.go:28 +0x31
main.main()
/Users/ola/code/ent/tsent/main.go:6 +0x20
command run was tsent codegen
output is below:
2020/03/18 10:50:58 wrote to file src/schema/schema.py
Generating /Users/ola/code/ent/ts/examples/simple/src/schema/versions/2d3f00438240_2020318175059_add_column_email_address_to_table_users_.py ... done
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1246, in _execute_context
cursor, statement, parameters, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 588, in do_execute
cursor.execute(statement, parameters)
psycopg2.errors.NotNullViolation: column "email_address" contains null values
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/ola/code/ent/python/auto_schema/gen_db_schema.py", line 37, in <module>
r.run()
File "/Users/ola/code/ent/python/auto_schema/auto_schema/runner.py", line 156, in run
self._apply_changes(diff)
File "/Users/ola/code/ent/python/auto_schema/auto_schema/runner.py", line 168, in _apply_changes
self.upgrade()
File "/Users/ola/code/ent/python/auto_schema/auto_schema/runner.py", line 222, in upgrade
self.cmd.upgrade()
File "/Users/ola/code/ent/python/auto_schema/auto_schema/command.py", line 40, in upgrade
command.upgrade(self.alembic_cfg, revision)
File "/usr/local/lib/python3.7/site-packages/alembic/command.py", line 276, in upgrade
script.run_env()
File "/usr/local/lib/python3.7/site-packages/alembic/script/base.py", line 475, in run_env
util.load_python_file(self.dir, "env.py")
File "/usr/local/lib/python3.7/site-packages/alembic/util/pyfiles.py", line 90, in load_python_file
module = load_module_py(module_id, path)
File "/usr/local/lib/python3.7/site-packages/alembic/util/compat.py", line 156, in load_module_py
spec.loader.exec_module(module)
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "/Users/ola/code/ent/python/auto_schema/auto_schema/env.py", line 137, in <module>
run_migrations_online()
File "/Users/ola/code/ent/python/auto_schema/auto_schema/env.py", line 130, in run_migrations_online
context.run_migrations()
File "<string>", line 8, in run_migrations
File "/usr/local/lib/python3.7/site-packages/alembic/runtime/environment.py", line 839, in run_migrations
self.get_context().run_migrations(**kw)
File "/usr/local/lib/python3.7/site-packages/alembic/runtime/migration.py", line 361, in run_migrations
step.migration_fn(**kw)
File "/Users/ola/code/ent/ts/examples/simple/src/schema/versions/2d3f00438240_2020318175059_add_column_email_address_to_table_users_.py", line 24, in upgrade
op.add_column('users', sa.Column('email_address', sa.Text(), nullable=False))
File "<string>", line 8, in add_column
File "<string>", line 3, in add_column
File "/usr/local/lib/python3.7/site-packages/alembic/operations/ops.py", line 1904, in add_column
return operations.invoke(op)
File "/usr/local/lib/python3.7/site-packages/alembic/operations/base.py", line 345, in invoke
return fn(self, operation)
File "/usr/local/lib/python3.7/site-packages/alembic/operations/toimpl.py", line 131, in add_column
operations.impl.add_column(table_name, column, schema=schema)
File "/usr/local/lib/python3.7/site-packages/alembic/ddl/impl.py", line 230, in add_column
self._exec(base.AddColumn(table_name, column, schema=schema))
File "/usr/local/lib/python3.7/site-packages/alembic/ddl/impl.py", line 134, in _exec
return conn.execute(construct, *multiparams, **params)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 982, in execute
return meth(self, multiparams, params)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/ddl.py", line 72, in _execute_on_connection
return connection._execute_ddl(self, multiparams, params)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1044, in _execute_ddl
compiled,
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1250, in _execute_context
e, statement, parameters, cursor, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1476, in _handle_dbapi_exception
util.raise_from_cause(sqlalchemy_exception, exc_info)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 398, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 152, in reraise
raise value.with_traceback(tb)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1246, in _execute_context
cursor, statement, parameters, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 588, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.IntegrityError: (psycopg2.errors.NotNullViolation) column "email_address" contains null values
[SQL: ALTER TABLE users ADD COLUMN email_address TEXT NOT NULL]
(Background on this error at: http://sqlalche.me/e/gkpj)
2020/03/18 10:50:59 cmd.Run() failed with exit status 1
ola@Olas-personal-MBP simple %
need to handle this because this will be something that for sure happens in real life. now it's all test data so can easily just delete table and start over.
need to provide a way for user to provide default or ask them to change it to nullable.
`ola@OlaspersonalMBP ent-rsvp % npm run codegen
[email protected] codegen /Users/ola/code/ent/examples/ent-rsvp
docker-compose -f docker-compose.dev.yml run --rm app tsent codegen
Creating ent-rsvp_app_run ... done
panic: could not find field id by name
actual id field is `ID`
right now, if something like #82 happens, we're left with a dangling schema.py
and dangling version file.
it's difficult to know what the state of things is without going to the db and checking the state of alembic_version
:
db=# select * from alembic_version ;
version_num
-------------
(0 rows)
db=#
when it's the first write, it's easy to tell
when it's not, it's even more difficult and one has to figure out what the right way to fix things
see #87
most things other than account create will prefer this
it makes the demo slightly more annoying but it'll lead to better outcomes eventually
we need to test every default operation and also write revisions/messages
right now it makes the db changes and then fails later on because of codegen
fails here...
checking for custom graphql definitions...
../../../../src/ent/generated/hours_of_operation_base.ts(20,20): error TS2307: Cannot find module 'src/schema/hours_of_operation' or its corresponding type declarations.
(node:85250) UnhandledPromiseRejectionWarning: Error: Cannot find module 'src/schema/hours_of_operation'
Require stack:
node --trace-warnings ...
to show where the warning was created)--unhandled-rejections=strict
(see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)Flags:
-h, --help help for codegen
-s, --step string limit to only run a particular step e.g. db, graphql, codegen
error unmarshalling custom data: unexpected end of JSON input
ola@OlaspersonalMBP simple % tsent codegen
ola@OlaspersonalMBP simple % tsent codegen
has been a longstanding TODO
fields: Field[] = [
StringType({ name: "FirstName" }),
StringType({ name: "FirstName" }),
...
should clearly fail
ent-password
: https://github.com/lolopinto/ent/blob/ts/ts/src/field/password.ts and https://github.com/lolopinto/ent/blob/ts/ts/src/field/password.test.tsent-phonenumber
: https://github.com/lolopinto/ent/blob/ts/ts/src/field/phonenumber.ts and https://github.com/lolopinto/ent/blob/ts/ts/src/field/phonenumber.test.tsent-emailaddress
: https://github.com/lolopinto/ent/blob/ts/ts/src/field/email.ts and https://github.com/lolopinto/ent/blob/ts/ts/src/field/email.test.tsgraphql-tests
?: https://github.com/lolopinto/ent/blob/ts/ts/examples/simple/src/graphql_test_utils/index.tstsc+
(better name needed): https://github.com/lolopinto/ent/blob/ts/ts/examples/simple/src/compiler.tsent-passport
(coming)when it's
actions: Action[] = [
{
operation: ActionOperation.Create,
fields: createFields,
// when all 3 presented, things are fine
actionName: "UserCreateRequesterAction",
graphQLName: "userCreateRequester",
inputName: "UserCreateRequesterInput",
},
{
operation: ActionOperation.Create,
fields: createFields,
actionName: "UserCreateVolunteerAction",
graphQLName: "userCreateVolunteer",
inputName: "UserCreateVolunteerInput",
},
];
it works, anything else, it doesn't
plus other issues referenced at #85
#109 chose not to generate unique methods in builder because it would be a lot of extra methods there and each generated builder already has a lot of methods:
It doesn't generate unique callsites in the builders yet because we want to avoid API bloat for now. Can add the generated callsites if this is a requested feature.
However, this leads to callsites needing to cast to and being ugly.
e.g. here's what a callsite after that change looks like:
const removedData = builder.getEdgeInputData(
EdgeType.OrganizationToMembers,
WriteOperation.Delete,
);
removedData.forEach((removed) =>
// so not needing this cast is why we want to generate this...
builder.addArchivedMemberID(removed.id as (Builder<Recipient> | ID)),
);
if it were generated, it'd be more like this
const removedData = builder.getRemovedMembers(); // or getRemovedInputData
removedData.forEach((removed) => builder.addArchivedMemberID(removed.id));
which is a lot easier to read since the return type would have been typed correctly too
we create field edges from field edge to source node and we end up hitting this error since we use the name of the edge to create the field edge
We need a way to name fieldEdges differently so we can name these things
e.g.
UUIDType({ name: "CreatorID", foreignKey: ["User", "ID"] }),
UUIDType({
name: "HelperID",
nullable: true,
// foreignKey: ["User", "ID"],
}),
2nd one fails because we end up with multiple User
-> Requests
edge so we need a way to name the edge
should be able to turn something on and figure out what rule is preventing an ent from being visible
right now order changes during code generation in both ent and gql land
UUIDType({ name: "CreatorID", foreignKey: ["User", "ID"] }),
gives
% tsent codegen
panic: could not find field id by name
goroutine 1 [running]:
github.com/lolopinto/ent/internal/schema.NodeMapInfo.addForeignKeyEdges(0xc0003c3080, 0xc0003fea20, 0xc0003e7720, 0xc000141710, 0xc0004005b0, 0xc0003f53e0)
/Users/ola/code/ent/internal/schema/node_map.go:338 +0x24c
github.com/lolopinto/ent/internal/schema.NodeMapInfo.addEdgesFromFields(0xc0003c3080, 0xc0003f5820)
/Users/ola/code/ent/internal/schema/node_map.go:315 +0xdf
github.com/lolopinto/ent/internal/schema.NodeMapInfo.buildPostRunDepgraph.func2(0xc0003f5820)
/Users/ola/code/ent/internal/schema/node_map.go:110 +0x34
github.com/lolopinto/ent/internal/schema.NodeMapInfo.processDepgrah.func1(0x15e3a60, 0xc0003fa3b0)
/Users/ola/code/ent/internal/schema/node_map.go:141 +0x4c
github.com/lolopinto/ent/internal/depgraph.(*Depgraph).Run(0xc0003f57c0, 0xc0001aba70)
/Users/ola/code/ent/internal/depgraph/depgraph.go:45 +0x1b4
github.com/lolopinto/ent/internal/schema.NodeMapInfo.processDepgrah(0xc0003c3080, 0xc0001e5940, 0xc0004050b0, 0xa, 0xc0003ec660)
/Users/ola/code/ent/internal/schema/node_map.go:136 +0xdb
github.com/lolopinto/ent/internal/schema.NodeMapInfo.parseInputSchema(0xc0003c3080, 0xc000010f78, 0x16d1ec3, 0xa, 0x100f8dd, 0x169c740, 0xc0003c3080)
/Users/ola/code/ent/internal/schema/node_map.go:618 +0x52e
github.com/lolopinto/ent/internal/schema.ParseFromInputSchema.func1(0xc0001e5780, 0xc0001e5780, 0x16c84d1, 0x3)
/Users/ola/code/ent/internal/schema/schema.go:42 +0x49
github.com/lolopinto/ent/internal/schema.parse(0xc0001abca0, 0x16ecbfa, 0x17, 0xc000028780)
/Users/ola/code/ent/internal/schema/schema.go:49 +0x68
github.com/lolopinto/ent/internal/schema.ParseFromInputSchema(0xc000010f78, 0x16d1ec3, 0xa, 0xc000010f78, 0x0, 0x0)
/Users/ola/code/ent/internal/schema/schema.go:41 +0x62
github.com/lolopinto/ent/tsent/cmd.glob..func1(0x1bfaba0, 0x1c2c7e0, 0x0, 0x0, 0x0, 0x0)
/Users/ola/code/ent/tsent/cmd/codegen.go:39 +0x87
github.com/spf13/cobra.(*Command).execute(0x1bfaba0, 0x1c2c7e0, 0x0, 0x0, 0x1bfaba0, 0x1c2c7e0)
/Users/ola/code/gocode/pkg/mod/github.com/spf13/[email protected]/command.go:826 +0x453
github.com/spf13/cobra.(*Command).ExecuteC(0x1bfb0a0, 0x104386a, 0x1bbd520, 0xc000000180)
/Users/ola/code/gocode/pkg/mod/github.com/spf13/[email protected]/command.go:914 +0x2fb
github.com/spf13/cobra.(*Command).Execute(...)
/Users/ola/code/gocode/pkg/mod/github.com/spf13/[email protected]/command.go:864
github.com/lolopinto/ent/tsent/cmd.Execute()
/Users/ola/code/ent/tsent/cmd/root.go:28 +0x31
main.main()
/Users/ola/code/ent/tsent/main.go:6 +0x20
1/ we need the object and referencing field e.g. Request.creatorID
2/ error message isn't clear
3/ there should be no stack traces
4/ for default fields like 'id', we should be lenient and support 'id', 'ID' and a few others
EntQuery will help a lot but we need a way for this to be handled by default and to be customized for each edge and/or project
there may be a missing flag that needs to be passed to the typescript compiler?
errors like this are not found by the new compiler but tsc
would have caught it
ola@Olas-personal-MBP simple % tsc
src/graphql/mutations/generated/contact/create_contact_action_type.ts:67:68 - error TS2345: Argument of type '{ emailAddress: string; firstName: string; lastName: string; }' is not assignable to parameter of type 'ContactCreateInput'.
Property 'userID' is missing in type '{ emailAddress: string; firstName: string; lastName: string; }' but required in type 'ContactCreateInput'.
67 let contact = await CreateContactAction.create(context.viewer, {
~
68 emailAddress: args.emailAddress,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
70 lastName: args.lastName,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
71 }).saveX();
~~~~~
src/ent/contact/actions/generated/create_contact_action_base.ts:16:3
16 userID: ID | Builder<User>;
~~~~~~
'userID' is declared here.
src/graphql/mutations/generated/event/create_event_action_type.ts:71:64 - error TS2345: Argument of type '{ name: string; startTime: Date; endTime: Date | null | undefined; location: string; }' is not assignable to parameter of type 'EventCreateInput'.
Property 'creatorID' is missing in type '{ name: string; startTime: Date; endTime: Date | null | undefined; location: string; }' but required in type 'EventCreateInput'.
71 let event = await CreateEventAction.create(context.viewer, {
~
72 name: args.name,
~~~~~~~~~~~~~~~~~~~~~~
...
75 location: args.location,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
76 }).saveX();
~~~~~
src/ent/event/actions/generated/create_event_action_base.ts:11:3
11 creatorID: ID | Builder<User>;
~~~~~~~~~
'creatorID' is declared here.
Found 2 errors.
It only works for edges that are in their own table
TODO in code still needs to be addressed: https://github.com/lolopinto/ent/blob/master/internal/db/db_schema.go#L491
partial indices probably what we want here: https://www.postgresql.org/docs/current/indexes-partial.html
never finished functionality when I added it...
similar to #61, if there's an error in code generation because of a typescript issue, it's not surfaced and it's a mystery what happened
so that the developer doesn't need to change anything to make it useful to start
In TypeScript. developer needs to do:
privacyPolicy: PrivacyPolicy = {
rules: [AllowIfViewerRule, AlwaysDenyRule],
};
to make the ent useful to start when that should just be the default
export default class RequestStatus implements Schema {
fields: Field[] = [
StringType({
name: "status",
primaryKey: true,
}),
];
enumTable = true;
dbRows = [
{
outcome: "OPEN",
},
{
outcome: "PENDING_FULFILLMENT",
},
{
outcome: "CLOSED",
},
];
}
and
EnumType({
name: "Status",
defaultValueOnCreate: () => "OPEN",
foreignKey: ["RequestStatus", "status"],
}),
in a different file don't work at the same time if there's already rows that have that step there:
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('request_statuses',
sa.Column('status', sa.Text(), nullable=False),
sa.PrimaryKeyConstraint(
'status', name='request_statuses_status_pkey')
)
op.create_foreign_key('requests_status_fkey', 'requests', 'request_statuses', [
'status'], ['status'], ondelete='CASCADE')
op.add_rows('request_statuses', ['status'], [
{'status': 'OPEN'},
{'status': 'PENDING_FULFILLMENT'},
{'status': 'CLOSED'},
])
# ### end Alembic commands ###
is generated and foreign key on OPEN without the rows being there is an issues
e.g. going from
actions: Action[] = [
{
operation: ActionOperation.Mutations,
},
];
to
actions: Action[] = [
{
operation: ActionOperation.Create,
},
];
deletes the edit and delete mutation from graphql schema but the graphql and action files are left dangling. would be nice to automatically delete this as opposed to leaving it to developer to do so
e9f3a0c dropped UserToUserToHostedEvents
edge but it still exists in the db after
It's not causing any harm but we should drop it
tsent_test=# select * from assoc_edge_config where edge_type = 'e5555185-91bf-4322-8130-d0a00eb605b7';
edge_type | edge_name | symmetric_edge | inverse_edge_type | edge_table | created_at | updated_at
--------------------------------------+------------------------------+----------------+--------------------------------------+-------------------+---------------------------+---------------------------
e5555185-91bf-4322-8130-d0a00eb605b7 | UserToUserToHostedEventsEdge | f | ebe3e709-845c-4723-ac9c-29f983f2b8ea | event_hosts_edges | 2020-10-22 22:48:25.77343 | 2020-10-22 22:48:25.77343
(1 row)
BooleanType({ name: "NeedsHelp", serverDefault: false }),
breaks with error
Generating /Users/ola/code/helping-hands-on-ent/src/schema/versions/a1973ac9e252_202073181625_add_users_table.py ... done
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1246, in _execute_context
cursor, statement, parameters, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 588, in do_execute
cursor.execute(statement, parameters)
psycopg2.errors.InvalidTextRepresentation: invalid input syntax for type boolean: "%!s(bool=false)"
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "auto_schema/gen_db_schema.py", line 37, in <module>
r.run()
File "/Users/ola/code/ent/python/auto_schema/auto_schema/runner.py", line 185, in run
self._apply_changes(diff)
File "/Users/ola/code/ent/python/auto_schema/auto_schema/runner.py", line 197, in _apply_changes
self.upgrade()
File "/Users/ola/code/ent/python/auto_schema/auto_schema/runner.py", line 251, in upgrade
self.cmd.upgrade()
File "/Users/ola/code/ent/python/auto_schema/auto_schema/command.py", line 40, in upgrade
command.upgrade(self.alembic_cfg, revision)
File "/usr/local/lib/python3.7/site-packages/alembic/command.py", line 276, in upgrade
script.run_env()
File "/usr/local/lib/python3.7/site-packages/alembic/script/base.py", line 475, in run_env
util.load_python_file(self.dir, "env.py")
File "/usr/local/lib/python3.7/site-packages/alembic/util/pyfiles.py", line 90, in load_python_file
module = load_module_py(module_id, path)
File "/usr/local/lib/python3.7/site-packages/alembic/util/compat.py", line 156, in load_module_py
spec.loader.exec_module(module)
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "/Users/ola/code/ent/python/auto_schema/auto_schema/env.py", line 137, in <module>
run_migrations_online()
File "/Users/ola/code/ent/python/auto_schema/auto_schema/env.py", line 130, in run_migrations_online
context.run_migrations()
File "<string>", line 8, in run_migrations
File "/usr/local/lib/python3.7/site-packages/alembic/runtime/environment.py", line 839, in run_migrations
self.get_context().run_migrations(**kw)
File "/usr/local/lib/python3.7/site-packages/alembic/runtime/migration.py", line 361, in run_migrations
step.migration_fn(**kw)
File "/Users/ola/code/helping-hands-on-ent/src/schema/versions/a1973ac9e252_202073181625_add_users_table.py", line 34, in upgrade
sa.PrimaryKeyConstraint('id', name='users_id_pkey')
File "<string>", line 8, in create_table
File "<string>", line 3, in create_table
File "/usr/local/lib/python3.7/site-packages/alembic/operations/ops.py", line 1248, in create_table
return operations.invoke(op)
File "/usr/local/lib/python3.7/site-packages/alembic/operations/base.py", line 345, in invoke
return fn(self, operation)
File "/usr/local/lib/python3.7/site-packages/alembic/operations/toimpl.py", line 101, in create_table
operations.impl.create_table(table)
File "/usr/local/lib/python3.7/site-packages/alembic/ddl/impl.py", line 251, in create_table
self._exec(schema.CreateTable(table))
File "/usr/local/lib/python3.7/site-packages/alembic/ddl/impl.py", line 134, in _exec
return conn.execute(construct, *multiparams, **params)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 982, in execute
return meth(self, multiparams, params)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/ddl.py", line 72, in _execute_on_connection
return connection._execute_ddl(self, multiparams, params)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1044, in _execute_ddl
compiled,
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1250, in _execute_context
e, statement, parameters, cursor, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1476, in _handle_dbapi_exception
util.raise_from_cause(sqlalchemy_exception, exc_info)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 398, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 152, in reraise
raise value.with_traceback(tb)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1246, in _execute_context
cursor, statement, parameters, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 588, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input syntax for type boolean: "%!s(bool=false)"
[SQL:
CREATE TABLE users (
id UUID NOT NULL,
created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
email_address TEXT,
phone_number TEXT NOT NULL,
bio TEXT,
can_help BOOLEAN DEFAULT '%%!s(bool=false)' NOT NULL,
needs_help BOOLEAN DEFAULT '%%!s(bool=false)' NOT NULL,
CONSTRAINT users_id_pkey PRIMARY KEY (id)
)
]
(Background on this error at: http://sqlalche.me/e/9h9h)
2020/07/31 01:16:25 cmd.Run() failed with exit status 1
Current acceptable format is
BooleanType({ name: "NeedsHelp", serverDefault: "false" }),
ola@OlaspersonalMBP simple % tsent codegen --step graphql
checking for custom graphql definitions...
(node:93884) UnhandledPromiseRejectionWarning: Error: type is required when accessor/function/property returns a Object
at Function.getResultFromMetadata (/Users/ola/code/ent/ts/examples/simple/node_modules/@lolopinto/ent/graphql/graphql.js:99:19)
at /Users/ola/code/ent/ts/examples/simple/node_modules/@lolopinto/ent/graphql/graphql.js:214:40
at Array.forEach (<anonymous>)
at Function.getCustomField (/Users/ola/code/ent/ts/examples/simple/node_modules/@lolopinto/ent/graphql/graphql.js:211:24)
at /Users/ola/code/ent/ts/examples/simple/node_modules/@lolopinto/ent/graphql/graphql.js:313:56
at DecorateProperty (/Users/ola/code/ent/ts/examples/simple/node_modules/reflect-metadata/Reflect.js:553:33)
at Object.decorate (/Users/ola/code/ent/ts/examples/simple/node_modules/reflect-metadata/Reflect.js:123:24)
at __decorate (/Users/ola/code/ent/ts/examples/simple/src/graphql/mutations/import_contact.ts:4:92)
at Object.<anonymous> (/Users/ola/code/ent/ts/examples/simple/src/graphql/mutations/import_contact.ts:8:3)
at Module._compile (internal/modules/cjs/loader.js:1256:30)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:93884) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:93884) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
([]uint8) (cap=512) {
}
Error: error unmarshalling custom data: unexpected end of JSON input
Usage:
tsent codegen [flags]
Flags:
-h, --help help for codegen
-s, --step string limit to only run a particular step e.g. db, graphql, codegen
error unmarshalling custom data: unexpected end of JSON input
ola@OlaspersonalMBP simple %
error was from this code:
export class ImportContactResolver {
@gqlMutation({ type: User })
async bulkUploadContact(
@gqlContextType() context: RequestContext,
@gqlArg("user") userID: ID,
@gqlArg("file") file: FileUpload,
) {
// TODO parse file
return await User.loadX(context.getViewer(), userID);
}
}
it was missing type in argument not returned object so that's confusing
also needs to be prettier without all the extra cruft but that's separate.
in the alembic compare scripts, we're not doing the right thing when it comes to multiple schemas
{
operation: ActionOperation.Edit,
// everything is optional by default in edits anyway
fields: ["FirstName", "LastName"],
},
{
operation: ActionOperation.Edit,
actionName: "EditEmailAddressAction",
graphQLName: "emailAddressEdit",
fields: [NoFields],
actionOnlyFields: [{ name: "emailAddress", type: "String" }],
},
results in multiple "UserEditInput" when we should do something like "EditEmailAddressInput" based on custom action name.
Also, we should throw when duplicate input names exist
e.g. max number of invites to a group a user can send etc
had an error that didn't show up and had to find it by running tsc
.
was easily fixable by just deleting a file but :(
ola@OlaspersonalMBP backend % ./node_modules/.bin/ent-custom-compiler
ola@OlaspersonalMBP backend % tsc
src/graphql/mutations/generated/event_activity/event_activityrsvp_status_edit_type.ts:16:3 - error TS2305: Module '"../../../resolvers"' has no exported member 'EventActivityRsvpStatusInputType'.
16 EventActivityRsvpStatusInputType,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Found 1 error.
In ComplexExecutor, there's a logic issue somewhere which is leading to double counting of operations. I "solved" that by using a set to keep track of operations but that same issue reared its head with some observers running multiple times which we don't want.
this is a pretty bad bug because it can mean emails being double sent, texts being double sent etc, things being double logged tc
Relevant code is at https://github.com/lolopinto/ent/blob/ts-observers/ts/src/executor.ts#L94-L139
could change the data structure/API around to make this work.
this live bug is manifested in some deeply nested observers being called multiple times. see https://github.com/lolopinto/ent/blob/master/ts/src/action/executor.test.ts#L608-L622 for the logging about contact being called twice.
just high level task here
we're always using actionPrefix
+ Input
e.g. given an address schema
export default class Address extends BaseEntSchema implements Schema {
fields: Field[] = [
StringType({ name: "Street" }),
StringType({ name: "City" }),
StringType({ name: "State" }),
StringType({ name: "ZipCode" }), // need to support US vs not, 5 or 9 letter zip codes
StringType({ name: "Apartment" }),
UUIDType({ name: "OwnerID", index: true, hideFromGraphQL: true }), // polymorphic. should require ID and Type together...
StringType({ name: "OwnerType", hideFromGraphQL: true }), // should be an enum
];
}
and multiple types which could have an address e.g. User, Store, etc
We should support polymorphic types natively so that it's something like:
export default class Address extends BaseEntSchema implements Schema {
fields: Field[] = [
StringType({ name: "Street" }),
StringType({ name: "City" }),
StringType({ name: "State" }),
StringType({ name: "ZipCode" }), // need to support US vs not, 5 or 9 letter zip codes
StringType({ name: "Apartment" }),
PolymorphicType({name: "Owner", index:true}), // this creates owner_id and owner_type fields, indexes on owner_id
];
}
^ should also create something along the lines of the following:
class AddressBase {
owner(): Ent {
// loadOwnEnt takes an id and NodeType and knows how to load ownerId based on the type
// this will also create Owner: Node in GraphQL
// can also create an interface in the future instead of Ent/Node here
return loadOwnEnt(this.ownerId, this.ownerType);
}
}
also needs this in the other object based on some reference that indicates the type of relationship?
// below is using a current incorrect API since there's nothing that indicates it's 1/1 (it assumes 1/1). if not, it should support 1-n also...
class UserBase {
@gqlField({ nullable: true, type: "Address" })
async address(): Promise<Address | null> {
// there's nothing that says there's only one of this
// this API is wrong...
return Address.loadFromOwnerID(this.viewer, this.id);
}
}
It assumes there's a 1-1 mapping but there can be one -to-n
we need to generate a different one to N API for this
UUIDType({
name: "OwnerID",
index: true,
hideFromGraphQL: true,
}),
generates
static async loadFromOwnerID<T extends AddressBase>(
this: new (viewer: Viewer, id: ID, data: Data) => T,
viewer: Viewer,
ownerID: ID,
): Promise<T | null> {
return loadEntFromClause(
viewer,
AddressBase.loaderOptions.apply(this),
query.Eq("owner_id", ownerID),
);
}
we can have multiple of these...
doesn't seem like this should be done by default but an opt-in way of doing that will be cool
e.g. having to write all this code is annoying
let input = builder.getInput();
let orgID = input.organizationID!;
let pickupLocationID = input.pickupLocationID!;
if (builder.isBuilder(orgID) || builder.isBuilder(pickupLocationID)) {
return;
}
let [org, pickupLocation] = await Promise.all([
Organization.load(builder.viewer, orgID),
PickupLocation.load(builder.viewer, pickupLocationID),
]);
if (!org || !pickupLocation) {
throw new Error('need to be able to load org and/or pickuplocation')
}
#128 is related too
tsent codegen --step graphql
checking for custom graphql definitions...
2020/10/30 00:39:09 wrote to file src/graphql/resolvers/generated/viewer_type.ts
2020/10/30 00:39:09 wrote to file src/graphql/resolvers/generated/address_type.ts
2020/10/30 00:39:09 wrote to file src/graphql/mutations/generated/user_auth_type.ts
2020/10/30 00:39:09 wrote to file src/graphql/mutations/generated/user_auth_jwt_type.ts
2020/10/30 00:39:09 wrote to file src/graphql/resolvers/generated/contact_type.ts
2020/10/30 00:39:09 wrote to file src/graphql/resolvers/generated/event_type.ts
2020/10/30 00:39:09 wrote to file src/graphql/resolvers/generated/user_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/mutations/generated/contact/contact_delete_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/event/event_to_invited_connection_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/event/event_to_declined_connection_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/event/event_to_attending_connection_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/event/event_to_maybe_connection_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/mutations/generated/event/event_create_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/mutations/generated/contact/contact_create_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/event/event_to_hosts_connection_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/mutations/generated/event/event_add_host_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/user/user_to_invited_events_connection_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/mutations/generated/contact/contact_edit_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/mutations/generated/event/event_edit_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/mutations/generated/event/event_delete_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/user/user_to_declined_events_connection_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/user/user_to_created_events_connection_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/user/user_to_friends_connection_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/user/user_to_events_attending_connection_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/user/user_to_hosted_events_connection_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/user/user_to_maybe_events_connection_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/mutations/generated/user/user_edit_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/mutations/generated/user/user_delete_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/mutations/generated/user/user_create_type.ts
2020/10/30 00:39:11 wrote to file src/graphql/resolvers/generated/query_type.ts
2020/10/30 00:39:12 wrote to file src/graphql/mutations/generated/mutation_type.ts
2020/10/30 00:39:12 wrote to file src/graphql/resolvers/internal.ts
2020/10/30 00:39:13 wrote to file src/graphql/resolvers/index.ts
/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:425
throw new Error("Expected ".concat((0, _inspect.default)(type), " to be a GraphQL nullable type."));
^
Error: Expected undefined to be a GraphQL nullable type.
at assertNullableType (/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:425:11)
at new GraphQLNonNull (/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:377:19)
at Object.GraphQLNonNull (/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:379:12)
at fields (/Users/ola/code/ent/ts/dist/graphql/query/connection_type.js:37:84)
at resolveThunk (/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:478:40)
at defineFieldMap (/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:690:18)
at GraphQLConnectionType.getFields (/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:631:27)
at collectReferencedTypes (/Users/ola/code/ent/ts/node_modules/graphql/type/schema.js:366:81)
at collectReferencedTypes (/Users/ola/code/ent/ts/node_modules/graphql/type/schema.js:368:9)
at collectReferencedTypes (/Users/ola/code/ent/ts/node_modules/graphql/type/schema.js:368:9)
(*os.File)(0xc0000a2008)({
file: (*os.file)(0xc0000a4060)({
pfd: (poll.FD) {
fdmu: (poll.fdMutex) {
state: (uint64) 0,
rsema: (uint32) 0,
wsema: (uint32) 0
},
Sysfd: (int) 1,
pd: (poll.pollDesc) {
runtimeCtx: (uintptr) <nil>
},
iovecs: (*[]syscall.Iovec)(<nil>),
csema: (uint32) 0,
isBlocking: (uint32) 1,
IsStream: (bool) true,
ZeroReadIsEOF: (bool) true,
isFile: (bool) true
},
name: (string) (len=11) "/dev/stdout",
dirinfo: (*os.dirInfo)(<nil>),
nonblock: (bool) false,
stdoutOrErr: (bool) true,
appendMode: (bool) false
})
})
(*os.File)(0xc0000a2010)({
file: (*os.file)(0xc0000a40c0)({
pfd: (poll.FD) {
fdmu: (poll.fdMutex) {
state: (uint64) 0,
rsema: (uint32) 0,
wsema: (uint32) 0
},
Sysfd: (int) 2,
pd: (poll.pollDesc) {
runtimeCtx: (uintptr) <nil>
},
iovecs: (*[]syscall.Iovec)(<nil>),
csema: (uint32) 0,
isBlocking: (uint32) 1,
IsStream: (bool) true,
ZeroReadIsEOF: (bool) true,
isFile: (bool) true
},
name: (string) (len=11) "/dev/stderr",
dirinfo: (*os.dirInfo)(<nil>),
nonblock: (bool) false,
stdoutOrErr: (bool) true,
appendMode: (bool) false
})
})
Error: error writing schema file: exit status 1
Usage:
tsent codegen [flags]
Flags:
-h, --help help for codegen
-s, --step string limit to only run a particular step e.g. db, graphql, codegen
error writing schema file: exit status 1
ola@OlaspersonalMBP simple %
parseCustomData
in generate_ts_code.go
It's annoying to always account for it so maybe it should be opt in
e.g. if you wanted to check if CreatorID was a valid User, having to check if isBuilder
is annoying.
sort should be as follows:
order:
also need to make sure to use src/graphql/resolvers/internal
in graphql/resolvers
paths and src/graphql/resolvers
in mutation paths
graphql
is a peer dependency and since the generated code assumes graphql
is installed, things just fail without it being obvious what the issue is
need to detect this issue and surface it and make it clearer graphql is required beforehand.
error just looks like
Error: error unmarshalling custom data: unexpected end of JSON input
Usage:
tsent codegen [flags]
Flags:
-h, --help help for codegen
-s, --step string limit to only run a particular step e.g. db, graphql, codegen
error unmarshalling custom data: unexpected end of JSON input
which isn't really helpful
it means that file is no longer valid
Running tsent codegen
afterwards leads to a schema is not up to date
error
some edges are strictly for data purposes and shouldn't be exposed in the public schema
e.g. archivedMembers of a group/event/organization etc
context: https://github.com/github/linguist#using-gitattributes
need these lines added:
models/configs/versions/* linguist-generated=true
models/configs/schema.py linguist-generated=true
need edge caching (like all caching that's needed):
need caching to make this faster
caching generally already on the list at https://github.com/lolopinto/ent/blob/7b522fe970e70f4411858e1b612655a234b3bba3/features.md#cache-support
specific caching that this applies to is more like: per request in memory cache (raw data)
under https://github.com/lolopinto/ent/blob/7b522fe970e70f4411858e1b612655a234b3bba3/features.md#ent-framework
adding an enum e.g. rainbow_type in tests at #113
generates the following code:
# Code generated by github.com/lolopinto/ent/ent, DO NOT edit.
"""add accounts table
Revision ID: bcfa772af8d3
Revises:
Create Date: 2020-08-22 08:37:36.040787+00:00
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'bcfa772af8d3'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('accounts',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('rainbow', sa.Enum('red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet', name='rainbow_type'), nullable=False),
sa.PrimaryKeyConstraint('id', name='accounts_id_pkey')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('accounts')
# ### end Alembic commands ###
there's no explicit create type but the type is created.
however, since no explicit create type, there ends up not being a drop type either
e.g. letting CreateUserAction
know that it's going to take fields from CreateAddressAction
and those can be passed along in a trigger
This will make it so that the data is modeled correctly, things can be in a transaction and there's only one mutation the client needs to care about instead of 2
played with multiple ways of integrating graphql in TypeScript. No obvious winner the way gqlgen seemed to be for go.
I think something nexus-like is probably what I want long-term assuming the schema is decoupled but it's just too early at the moment and I couldn't immediately get it to work the day I tried. I assume I did something wrong here.
type-graphql is cool and seems to work well. However, uses reflection at runtime which isn't officially supported yet and is dependent on decorators and reflect-metadata which I suspected would negatively affect performance.
Everything in JS land seems to eventually boil down to being built on graphql-js itself anyways. It seems like express-graphql, graphql-yoga, apollo-server etc all take the GraphQLSchema generated from the schema and do things with it.
Considering most of the graphql code here will be codegenned, it seems the best thing is to skip most of the extra stuff that comes with all these other frameworks and just use graphql-js directly. And then eventually provide options for clients to use whichever graphql server they want if they need other features that aren't supported in the default implemention. And since the same schema should theoretically be passable to all the other frameworks, it should be fine.
One thing that type-graphql does is provide an easy way to have custom code since it'll be the same format being used by custom and non-custom code. To figure out if the presumed overhead of runtime reflection we'd get here was worth it, I did some simple profiling based on https://nodejs.org/en/docs/guides/simple-profiling/.
Quick profiling shows that there's a 2x overhead that comes with reflection at runtime if my numbers are to be believed.
I ran ab -k -p postfile.txt -c 20 -n 250 -H 'Content-Type: application/json' http://localhost:4000/graphql/
for both the type-graphql
and graphql-js
implementations and ended up with the following results:
tye-graphql (first time)
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests
Server Software:
Server Hostname: localhost
Server Port: 4000
Document Path: /graphql/
Document Length: 148 bytes
Concurrency Level: 20
Time taken for tests: 0.228 seconds
Complete requests: 250
Failed requests: 0
Non-2xx responses: 250
Keep-Alive requests: 250
Total transferred: 107250 bytes
Total body sent: 119500
HTML transferred: 37000 bytes
Requests per second: 1094.89 [#/sec] (mean)
Time per request: 18.267 [ms] (mean)
Time per request: 0.913 [ms] (mean, across all concurrent requests)
Transfer rate: 458.70 [Kbytes/sec] received
511.09 kb/s sent
969.79 kb/s total
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.2 0 2
Processing: 7 17 7.6 16 52
Waiting: 7 17 7.6 15 52
Total: 7 17 7.7 16 53
Percentage of the requests served within a certain time (ms)
50% 16
66% 18
75% 20
80% 20
90% 23
95% 26
98% 50
99% 51
100% 53 (longest request)
(2nd time)
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests
Server Software:
Server Hostname: localhost
Server Port: 4000
Document Path: /graphql/
Document Length: 148 bytes
Concurrency Level: 20
Time taken for tests: 0.282 seconds
Complete requests: 250
Failed requests: 0
Non-2xx responses: 250
Keep-Alive requests: 250
Total transferred: 107250 bytes
Total body sent: 119500
HTML transferred: 37000 bytes
Requests per second: 885.84 [#/sec] (mean)
Time per request: 22.577 [ms] (mean)
Time per request: 1.129 [ms] (mean, across all concurrent requests)
Transfer rate: 371.12 [Kbytes/sec] received
413.51 kb/s sent
784.63 kb/s total
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.3 0 2
Processing: 2 21 12.7 17 78
Waiting: 2 21 12.7 17 78
Total: 2 21 12.6 17 78
Percentage of the requests served within a certain time (ms)
50% 17
66% 25
75% 26
80% 29
90% 39
95% 47
98% 55
99% 55
100% 78 (longest request)
graphql-js
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests
Server Software:
Server Hostname: localhost
Server Port: 4000
Document Path: /graphql
Document Length: 53 bytes
Concurrency Level: 20
Time taken for tests: 0.139 seconds
Complete requests: 250
Failed requests: 0
Non-2xx responses: 250
Keep-Alive requests: 250
Total transferred: 68500 bytes
Total body sent: 119500
HTML transferred: 13250 bytes
Requests per second: 1803.56 [#/sec] (mean)
Time per request: 11.089 [ms] (mean)
Time per request: 0.554 [ms] (mean, across all concurrent requests)
Transfer rate: 482.59 [Kbytes/sec] received
841.89 kb/s sent
1324.49 kb/s total
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.2 0 1
Processing: 5 8 2.7 7 37
Waiting: 5 8 2.6 7 36
Total: 5 8 2.7 7 37
Percentage of the requests served within a certain time (ms)
50% 7
66% 8
75% 8
80% 8
90% 10
95% 12
98% 14
99% 16
100% 37 (longest request)
(2nd time)
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests
Server Software:
Server Hostname: localhost
Server Port: 4000
Document Path: /graphql
Document Length: 53 bytes
Concurrency Level: 20
Time taken for tests: 0.120 seconds
Complete requests: 250
Failed requests: 0
Non-2xx responses: 250
Keep-Alive requests: 250
Total transferred: 68500 bytes
Total body sent: 119500
HTML transferred: 13250 bytes
Requests per second: 2086.64 [#/sec] (mean)
Time per request: 9.585 [ms] (mean)
Time per request: 0.479 [ms] (mean, across all concurrent requests)
Transfer rate: 558.34 [Kbytes/sec] received
974.04 kb/s sent
1532.37 kb/s total
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 1 7 1.9 7 24
Waiting: 1 7 1.9 7 23
Total: 1 8 1.9 7 24
Percentage of the requests served within a certain time (ms)
50% 7
66% 7
75% 7
80% 8
90% 9
95% 11
98% 14
99% 16
100% 24 (longest request)
and the contents of postfile.txt
:
cat postfile.txt
{"query":"{viewer {user {id,emailAddress,firstName,lastName,accountStatus,selfContact {id,firstName,lastName,emailAddress,},contacts {id,firstName,lastName,emailAddress,user {id,firstName,}},friends {id,firstName,lastName,},friendsCount,createdEvents {id,name,startTime,endTime,}}}}"}
based on these, going to implement graphql-js directly for TypeScript GraphQL integration but will also need to implement decorators which will be used for custom graphql integrations which will be determined statically to generate the graphql code similar to what we do for go.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.