WICG / webmonetization

Proposed Web Monetization standard
https://webmonetization.org
Other
480 stars 154 forks source link

`ReadableStream` vs `progress` Event vs both #27

Closed adrianhopebailie closed 3 years ago

adrianhopebailie commented 5 years ago

From web-monetization created by sublimator: adrianhopebailie/web-monetization#25

@marcoscaceres and I started discussing this in brief in #24

adrianhopebailie commented 5 years ago

I think what I'm drawing out of that comment is that the "content creator" site might actually want the ability to "pause" a stream as well?

So someone goes to mymoneytube.com and is playing some songs, they press pause for a bit, and then without having to also pause separately as part of some external WM controls, the stream is paused ?

adrianhopebailie commented 5 years ago

Yes, precisely @sublimator. @adrianhopebailie, was there some rationale for not really supporting the above in the current design? Was it just for simplicity? I think it could be possible to support both models in the spec... the declarative model could just be "pay me now!"... while the . monetization. object could provide a means for finer-grained control.

adrianhopebailie commented 5 years ago

I think I recall you mentioning something about (edit: use backquotes for <link>) <link> tags instead of meta. I've not really let myself think much past the current design, but vaguely pondered some kind of container tags for monetized content. Think like a scrolling page of videos / images.

adrianhopebailie commented 5 years ago

Ah, that reminds me... we need to add SecureContext to the IDL interfaces to make them only exposed in HTTPS.

adrianhopebailie commented 5 years ago

Was it just for simplicity

@sharafian / Ben wrote most of the spec. He's still traveling Japan :) But I get the feeling, yes, it was all kept quite simple. Simplicity/Complexity infects everything. At first the tags were meant only for static, server sent (ideally via https) documents, where the stream would just start and last for the lifetime of the page.

Later we added a MutationObserver observer to the head, to support the coil.com SPA site.

adrianhopebailie commented 5 years ago

I'm envisioning a case where the content publisher only wants to monetize when the user is interacting or consuming a particular content: for example, the user starts actively engaging with some media (audio, video, canvas, whatever). The user might pause the media, hence the monetization stream could also be paused and resumed.

Streams seem well suited to model the use case above, as opposed to the current eventing model where money just floods in irrespective of what the user is doing. From this perspective, a stream API might give content producers and users better control over negotiating how payments are streamed and a better sense of control over what the user is paying for.

adrianhopebailie commented 5 years ago

There were some norms in the music industry that 30s preview is free of charge(or varies in the duration), so there was samplings edition that users can freely try and decide. For music, which we are working on( github.com/musiocin), the technical model is to stream it, but the consumption model can be different from service to service, e.g. charge by traffic or minutes, or track, etc. The key challenge is not on how to trigger the payment, is on how to validate the playback and how flexible a contract can be hooked behind.

adrianhopebailie commented 5 years ago

There is a reasonable example on MDN that shows how they work with a fetch request's body: https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams

adrianhopebailie commented 5 years ago

Thanks @immartian for the clarification. I'm still wondering about the flexibility afforded by streams over events. At first glance, it feels like streams provide more flexibility and control to all parties than the eventing model, but still something we would need to explore in detail.

adrianhopebailie commented 5 years ago

I still don't grok how streams in the browser work, esp. for things other than streams of data. are there any good explanations online of how streams API works?

adrianhopebailie commented 5 years ago

We were thinking of this in terms of incentives when we wrote the spec initially. Even if a user isn't actively streaming content, the site should still want to monetize the user's time on the page. The idea that the user or site would want to not monetize suggests that there are flaws somewhere else in the design of Web Monetization: the goal for WM to be a frictionless way for a site to monetize that doesn't require user consent and shouldn't worsen the user's experience in any way.

That said with the ability to dynamically add/remove the meta tag you can turn monetization on/off at will. We may want to add an imperative API (document.monetization.stop(), document.monetization.start(paymentPointer))in addition to the declarative one because dynamically adding/removing meta tags all the time can get a bit janky.

adrianhopebailie commented 5 years ago

I think it would be useful to show a code example of consuming a stream vs events.

Here's my best effort.

This assumes that we'll have something like monetization.paymentStream that is a ReadableStream which is a stream of objects that each represent a successful payment.


let pause = false;

window.addEventListener('load', startPayments);

function startPayments() {
    pause = false;
    handlePayments(monetization.paymentStream.getReader());
}

function pausePayments() {
    pause = true;
}

function handlePayments(reader) {
    reader.read().then(
        ({ value, done }) => {
            if (done) {
                // The stream was closed, this is a terminal event (i.e. not paused)
                console.log(`The stream was closed!`);
            } else {
                // Handle next payment
                console.log(`Got paid ${value.amount}!`)

                if(!pause) {
                    // Recursively call
                    handlePayments(reader);
                }
            }
        },
        e => console.error(`The stream threw an error.`, e)
    );
}

I assume this will be even cleaner with async iterators

adrianhopebailie commented 5 years ago

PROPOSAL

Based on the discussion so far we should at least add a ReadableStream to the interface that websites can use to read incoming payments.

We can leave the events too and see which developers prefer over time.

We should do this as part of the global interface (See #24)

Please respond to this proposal with either an 👍 or a 👎

If you are 👎 on this proposal please provide rationale below

sublimator commented 5 years ago

While I haven't personally been attracted to what I've read/seen so far, I'm in favor of trialing a Streams interface simply by virtue of others wanting it. Again, I think a Preview/Next/Alpha/Whatever release track would help here, so we can experiment and get feedback.

adrianhopebailie commented 5 years ago

I think a Preview/Next/Alpha/Whatever release track would help here, so we can experiment and get feedback.

Can you say which features you think would be in this track and why they can't just be deployed in the main track?

sublimator commented 5 years ago

Can you say which features you think would be in this track

It wouldn't matter if I couldn't.

It's not about features so much as iterations of such features and allowing people to test and give feedback before rolling out. Generally it's good to get initial feedback from a small circle of interested/motivated testers that don't mind breaking changes. Even when developing demos where hardly one is using them, it's paid to have multiple tracks/environments, if only to allow people to demo something stable to prospective clients, while having an internal development track. Rings ...

Android play store has this:

[image: image.png]

Apple has TestFlight with similar features.

sharafian commented 5 years ago

:-1: Not sure how we'd actually map a ReadableStreams API to the WM api

STREAM doesn't have any concept of packet-based backpressure, only amount-based backpressure. And we don't want the site to have to specify the amount when it uses the iterator so really a time-based start/stop is all we can practically do. Basically the mapping from iterations in the web streams API doesn't map to anything in the STREAM protocol nicely.

adrianhopebailie commented 5 years ago

Not sure how we'd actually map a ReadableStreams API to the WM api

I think this is worth exploring but I'd guess something like adjusting the maxReceive between 0 and MAX depending on whether or not someone is reading the stream.

sharafian commented 5 years ago

You can't decrease receiveMax. I suppose you could sever the stream as a "backpressure" mechanism but then we waste a tremendous amount of time reopening it and closing it if someone has written code that requires us to wait

sidvishnoi commented 3 years ago

Suppose we've a monetization.paymentStream.getReader() and we're iterating over it. What should happen if the payment pointer (which is indirectly the stream source) is changed? Should this be:

Also, the stream API sounds more like a pull API (if we can pause), whereas the events are a push API. What maps better to the backend?

marcoscaceres commented 3 years ago

Thinking about this a little more, I'm in agreement with @sharafian in that it doesn't map well to a stream. The payment progress are discrete units of payment, and not something that progresses to an aggregate payment (i.e., like @sharafian said, there is no back pressure and there is no steaming until done).

marcoscaceres commented 3 years ago

closing, as we will stick to the simple eventing model...