Implement a Result type in Drupal Core

Created on 3 March 2024, 4 months ago
Updated 19 April 2024, 2 months ago

Problem/Motivation

As we start doing more things asynchronously we'll have more batched work that can succeed and fail. In those kinds of scenario's an exception would cancel out the entire batch, even though it's often desirable to have a single item in a batch file while the rest of the batch continues.

Other (functional) languages solve this by providing a Result type that can be Ok or Error. By making clever use of the type-system this allows communicating that something can fail and forces the calling code to either deal with the success and error case (making sure not to forget one) or to propagate the result (optionally transforming the Ok or Error case).

PHP does not have a type like this itself so some custom code is needed. It's a capability that we will want to use in Drupal Core (e.g. for asynchronously processing BigPipe or rendering tasks where item-errors don't stop the entire process) and where contrib will want to standardise on a shared type for interoperability.

Steps to reproduce

Proposed resolution

Implement a Drupal/Core/Result (or should it be Drupal/Component/Result?) type that uses PHPStan types to implement the same logic as is available in functional programming languages (on Error you'll get the Error Type and on Ok you get the Ok Type).

An example implementation exists in https://phpstan.org/r/e9c7213e-b7ad-47f8-93b4-ec19e479b688 which is waiting for a small bit of PHPStan support and not quite ready for implementation in Drupal.

Remaining tasks

  • Agree on the namespace of the new class
  • Fix the existing PHPStan error (which is detected at Level 3 and above)
  • Create MR
  • Write release notes snippet

User interface changes

API changes

Drupal introduces a new Result type which can be used to communicate that the result of an action can be successful or failure and that such a failure is not an exceptional circumstance (i.e. does not warrant an Exception). The Result class is typed in such a way that calling code can get type-hints of the types produced for either case.

Data model changes

Release notes snippet

✨ Feature request
Status

Needs work

Version

11.0 πŸ”₯

Component
BaseΒ  β†’

Last updated 1 minute ago

Created by

πŸ‡³πŸ‡±Netherlands Kingdutch

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @Kingdutch
  • Status changed to Needs work 4 months ago
  • πŸ‡³πŸ‡±Netherlands Kingdutch

    Added a merge request to show the proposed implementation. However this "Needs Work" because we can't quite tell PHPStan what we want to do :)

    However, this allows async issues to start using the type and demonstrate its usefulness.

  • Pipeline finished with Failed
    4 months ago
    Total: 177s
    #109592
  • Status changed to Needs review 4 months ago
  • πŸ‡³πŸ‡±Netherlands Kingdutch

    I've asked for some help in the PHPStan discussions on GitHub and Ondrej was very kind in providing more insights: https://github.com/phpstan/phpstan/discussions/10667. It turns out I was running into a known issue https://github.com/phpstan/phpstan/issues/6732.

    I've now pushed a workaround using a type annotation :)

  • Pipeline finished with Failed
    4 months ago
    Total: 163s
    #112625
  • Status changed to Needs work 4 months ago
  • The Needs Review Queue Bot β†’ tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

    This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide β†’ to find step-by-step guides for working with issues.

  • Status changed to Needs review 4 months ago
  • πŸ‡³πŸ‡±Netherlands Kingdutch

    This was failing on some coding standards (parts of which is PHPCS not yet understanding more complex PHPStan types). These were fixed in a commit amend.

  • Pipeline finished with Success
    4 months ago
    Total: 488s
    #112737
  • πŸ‡³πŸ‡±Netherlands Kingdutch

    I missed Catch's feedback on the missing bool return types for isOk/isError which I've now added :D

  • Pipeline finished with Success
    4 months ago
    Total: 572s
    #115274
  • πŸ‡«πŸ‡·France andypost

    It looks straightforward so not sure a test needed.

    But it needs CR with example of use to announce it to module developers and maybe follow-up to apply monadic result to some core places

  • πŸ‡³πŸ‡±Netherlands Kingdutch

    I wasn’t quite sure how to test it. I suppose we could test that the isOk and isError types do what they say.

    What I’ve previously done is write a few function calls around it with PHPStan at level 9 to make sure all the type annotations had the right behavior. We don’t really have infrastructure for that though and that should be solidified when we adopt it :)

    See the linked PHPStan sandbox for that bit of code

    I’ll write a CR proposal in the coming days unless someone is faster

  • Pipeline finished with Canceled
    4 months ago
    Total: 53s
    #115812
  • Pipeline finished with Success
    4 months ago
    Total: 619s
    #115813
  • Pipeline finished with Success
    4 months ago
    Total: 549s
    #115830
  • πŸ‡³πŸ‡±Netherlands Kingdutch

    I've applied the suggested changes to the documentation and removed the sentence about the list example, instead showing it as code which I hope helps it more easily click with developers.

  • Pipeline finished with Success
    3 months ago
    Total: 509s
    #121563
  • Status changed to Needs work 2 months ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Nice!

    Shouldn't we have test coverage though to make sure this does what is expected?

Production build 0.69.0 2024