Skip to content

Commit

Permalink
feat: add Workflows to ValidationErrorReporter
Browse files Browse the repository at this point in the history
In order to have proper validation for Workflows I think we will need a
similar setup as DOs: ValidationErrorReporter now has a
`addWorkflowClass` that behaves similarily as `addActorClass`. (This
will need a internal PR in order to work properly).

This will be useful in cases that a user exports a class but doesn't
extend from `WorkflowEntrypoint` (meaning they won't get `ctx` and
`env` and see weird errors).
  • Loading branch information
LuisDuarte1 committed Feb 6, 2025
1 parent be15d2e commit eda2f27
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/workerd/io/worker.c++
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ struct Worker::Impl {
kj::HashMap<kj::String, api::ExportedHandler> namedHandlers;
kj::HashMap<kj::String, ActorClassInfo> actorClasses;
kj::HashMap<kj::String, EntrypointClass> statelessClasses;
kj::HashMap<kj::String, EntrypointClass> workflowClasses;

// If set, then any attempt to use this worker shall throw this exception.
kj::Maybe<kj::Exception> permanentException;
Expand Down Expand Up @@ -1690,7 +1691,7 @@ Worker::Worker(kj::Own<const Script> scriptParam,
impl->statelessClasses.insert(kj::mv(handler.name), kj::mv(cls));
return;
} else if (handle == entrypointClasses.workflowEntrypoint) {
impl->statelessClasses.insert(kj::mv(handler.name), kj::mv(cls));
impl->workflowClasses.insert(kj::mv(handler.name), kj::mv(cls));
return;
}

Expand Down Expand Up @@ -2206,6 +2207,17 @@ void Worker::Lock::validateHandlers(ValidationErrorReporter& errorReporter) {
"did not produce a startup-time error.");
}
}
for (auto& entry: worker.impl->workflowClasses) {
KJ_IF_SOME(entrypointName, getEntrypointName(entry.key)) {
errorReporter.addWorkflowClass(entrypointName);
} else {
// Similiar to Durable Objects, Workflow cannot be the default entrypoint (at the time of writing).
LOG_PERIODICALLY(ERROR,
"Exported Workflow class cannot be the default entrypoint. This doesn't work, but historically "
"did not produce a startup-time error.");
}
}

for (auto& entry: worker.impl->statelessClasses) {
// We want to report all of the stateless class's members. To do this, we examine its
// prototype, and it's prototype's prototype, and so on, until we get to Object's
Expand Down
7 changes: 7 additions & 0 deletions src/workerd/io/worker.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ class Worker: public kj::AtomicRefcounted {

// Report that the Worker exports a Durable Object class with the given name.
virtual void addActorClass(kj::StringPtr exportName) = 0;

// Report that the Worker exports a Workflow class with the given name.
virtual void addWorkflowClass(kj::StringPtr exportName) = 0;
};

class LockType;
Expand Down Expand Up @@ -894,6 +897,10 @@ struct SimpleWorkerErrorReporter final: public Worker::ValidationErrorReporter {
KJ_UNREACHABLE;
}

void addWorkflowClass(kj::StringPtr exportName) override {
KJ_UNREACHABLE;
}

SimpleWorkerErrorReporter() = default;
KJ_DISALLOW_COPY_AND_MOVE(SimpleWorkerErrorReporter);
kj::Vector<kj::String> errors;
Expand Down
4 changes: 4 additions & 0 deletions src/workerd/server/server.c++
Original file line number Diff line number Diff line change
Expand Up @@ -3150,6 +3150,10 @@ kj::Own<Server::Service> Server::makeWorker(kj::StringPtr name,
void addActorClass(kj::StringPtr exportName) override {
actorClasses.insert(kj::str(exportName));
}

void addWorkflowClass(kj::StringPtr exportName) override {
// This is only used for validation and has no runtime implications, at least for now.
}
};

ErrorReporter errorReporter(*this, name);
Expand Down
1 change: 1 addition & 0 deletions src/workerd/tests/test-fixture.c++
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ struct MockErrorReporter final: public Worker::ValidationErrorReporter {

void addEntrypoint(kj::Maybe<kj::StringPtr> exportName, kj::Array<kj::String> methods) override {}
void addActorClass(kj::StringPtr exportName) override {}
void addWorkflowClass(kj::StringPtr exportName) override {}
};

inline server::config::Worker::Reader buildConfig(
Expand Down

0 comments on commit eda2f27

Please sign in to comment.