Coder Social home page Coder Social logo

Comments (8)

ryanbliss avatar ryanbliss commented on May 30, 2024 1

Hey @nmtoblum, yeah this is great feedback, thank you for being so thorough! We have some work to do in this area for sure. While we are formally releasing @microsoft/live-share, -media, and -canvas to v1.0.0 at Build in a couple weeks, the React & Turbo packages will stay in Preview. So we're still working some of this out, but I will make a note to ensure that the error messages be more consistent across these three paradigms.

What you are touching on here relates to how Fluid Framework works. Basically, anything that is in initialObjects from your ContainerSchema is created before the IFluidContainer is created, and currently they don't support changing those initialObjects after the container is created.

So I asked myself how this situation could be handled in Teams where maybe more then one live-share-* app is started in the same meeting. The first will win? But how should the second app handle this?

These containers are stored in our server for about 6 hours after you first install the app to a meeting, before we delete them. Each unique application in Teams gets one container per meeting, meaning that apps do not get access to any other container you have already created.

This is determined by two things, which we do primarily for security reasons and to avoid the issue which you mentioned above:

  1. Your application's unique id, as determined in your app manifest
  2. The origin URL of your application

That means that even if an app has the same identifier as you, if your origin is different then you will have two separate containers for a single meeting. You won't have any conflicts with other Teams apps, just your own while you are testing a different app schema within the same 6 hour window.

This gives you two ways to "reset" your container while you're still flushing out your app & schema:

  1. Simply create a new meeting and sideload it there. Meet Now meetings are the easiest way for this, generally.
  2. Change one character of your "id" in your app manifest and reinstall. Obviously you want a static app ID for your production app, but there is nothing stopping you from changing it as many times as you'd like during development. Usually we just do a new meeting though, since zipping the manifest and uploading the new app package is a bit clunky.

RE: other stuff mentioned

Containers created by LiveShareTurboClient (and consequentially live-share-react) are not compatible with that from the regular LiveShareClient. This is because Live Share Turbo actually abstracts away the schema so you don't have this issue. LiveShareTurboClient uses a single initialObjects entry called DynamicObjectsManager, which is what you're seeing in that first error message. It is the same as if you did this in the Live Share client:

import { LiveShareClient, TestLiveShareHost } from "@microsoft/live-share";
import { DynamicObjectsManager } from "@microsoft/live-share-turbo";

const schema = {
  initialObjects: {
    TURBO_STATE_MAP: DynamicObjectsManager,
  },
  dynamicObjectTypes: [...every DDS possible in your app],
}

We might change this in a future update -- we are talking with the Fluid Framework team about how we could create the TURBO_STATE_MAP without depending on initialObjects at all (effectively doing what they do under the hood w/ initialObjects, rather than adding an additional abstraction). However, it does mean that you can get some portability between live-share-react and live-share-turbo, as long as you are using the same keys for each DDS.

For example, if you use this in React:

import { useLiveState } from "@microsoft/live-share-react";

const FOO_KEY= "foo";
export const SomeComponent = () => {
  const [foo, setFoo] = useLiveState<string>(FOO_KEY, "bar");
  return (
    <div>
      {foo}
    </div>
  );
}

That is the same as this in live-share-turbo:

import { LiveShareTurboClient } from "@microsoft/live-share-turbo";
import { LiveState, TestLiveShareHost } from "@microsoft/live-share";

const FOO_KEY= "foo";

const host = TestLiveShareHost.create();
const client = new LiveShareTurboClient(host);
await client.join();

const fooState = await client.getDDS(FOO_KEY, LiveState);
fooState.on("stateChanged", (latest) => {
  // update app
});
await fooState.initialize("bar");

Technically you could make the LiveShareClient work with Turbo client as well, if you were really motivated, though at that point you might as well just use LiveShareTurboClient.

Hope this helps! Happy to answer more questions, and definitely keep sharing candid feedback, it's super helpful!

from live-share-sdk.

nmtoblum avatar nmtoblum commented on May 30, 2024

One thing I wanted to add: To get a better understanding what happens here and to reduce complexity, I took another step back and tried to implement a similar minimal solution with live-share-turbo. It's in this branch: https://github.com/toblum/spotalot/tree/live-share-turbo

When running this code I always get this error message:
image

This happens every time when this line is executed: https://github.com/toblum/spotalot/blob/c95e8e6de9b6c2ce7a5382711f186703ee98e8d7/client/src/pages/SidePanel.tsx#L19

I think that could be related as I saw this error also when using live-share-react.

Greetings
Tobias

from live-share-sdk.

nmtoblum avatar nmtoblum commented on May 30, 2024

And I even went back one more step and tried the same as vanilla live-share:
https://github.com/toblum/spotalot/tree/minimal

Here I always get the error: Error: Registry does not contain entry for the package

image

Now I'm at the end of my rope. I have no idea what I did wrong here.

Would be great if you could give me a hint what's happening here.

Greetings
Tobias

from live-share-sdk.

ryanbliss avatar ryanbliss commented on May 30, 2024

Hey @nmtoblum, thanks for reporting this! Thanks for linking to your test project, I will see if I can repro on my machine and get back to you ASAP.

from live-share-sdk.

ryanbliss avatar ryanbliss commented on May 30, 2024

One thing I noticed, which we have done a poor job at documenting...@fluidframework/azure-client version 1.1 or greater have an issue right now because of a breaking change they introduced that we only recently caught. If you are testing in Teams, that would probably line up with the AzureUser issue you were seeing.

We have a server-side patch coming next week, but in the meantime if you change the @fluidframework/azure-client version to "~1.0.2" that should at least fix that issue.

As for this one:

And I even went back one more step and tried the same as vanilla live-share:
https://github.com/toblum/spotalot/tree/minimal

Here I always get the error: Error: Registry does not contain entry for the package

This is probably because you were testing in the same meeting as before. This is something Live Share Turbo / React are meant to help. Because the container was created using the Live Share Turbo structure, that means the schema you defined for the base client mismatched that of what is used in Turbo/React. The base Live Share package doesn't yet support migrating schema, but to fix you can just create a new meeting and test from there.

Let me know if this helps!

from live-share-sdk.

ryanbliss avatar ryanbliss commented on May 30, 2024

Also this isn't the issue, but I noticed the following:

const { created } = useLiveShareContext();
const host = TestLiveShareHost.create();
return (
		<div>
			SidePanel
			<LiveShareProvider joinOnLoad host={host}>
				LSP
				{created}
				<GameSettings></GameSettings>
			</LiveShareProvider>
		</div>
);

First issue, useLiveShareContext(); should only be accessed from within a child component. I would nest another component within SidePanel.tsx, because otherwise that will always be undefined. Also, created is referring to whether the local user was the one to create the container.

The second is regarding the host. Generally, you should either wrap those in a useState or even define it outside of the component. This will ensure it doesn't re-create the object on every render.

I would recommend something closer to the following:

import { LiveShareProvider, useFluidObjectsContext } from "@microsoft/live-share-react";
import { LiveShareHost } from "@microsoft/live-share";
import { useState } from "react";

const SidePanel = () => {
  // teams-js must be initialize before LiveShareHost.create() will work
  const [host] = useState(LiveShareHost.create());
  return (
    <LiveShareProvider host={host} joinOnLoad>
      <SidePanelRenderer />
    </LiveShareProvider>
  )
}

const SidePanelRenderer = () => {
  const { container } = useFluidObjectsContext();
  if (!container) return (<Spinner />);
  return (<GameSettings />);
}

from live-share-sdk.

nmtoblum avatar nmtoblum commented on May 30, 2024

Hi Ryan,

thanks for your quick reply and for taking the time to investigate my problem.

The note about the version of @fluidframework/azure-client was spot on. That solved a lot of things already:

  • minimal: The error Registry does not contain entry for the package is gone and I think I could build a vanilla live-share solution now. I have not tested further yet.
  • live-share-turbo: This solution works now too.
  • live-share-react: With your code example it works now too. I probably oversimplified the code a bit during my tests. :-)

At first, however, no variant worked and the error messages were confusing, but I drilled a little deeper and I think I understood why my tests over the last few days gave such confusing results:

I always tested in teams meetings. Today, I tested the "minimal" example first and tried it successfully (that registered an exampleMap in the Fluid container). Then I tried the live-share-turbo solution in the same meeting. That then failed with an error message that looked like this:
image

Then I tried live-share-react example and got this error message:
image

The error happens here:
image

I made sure that the container exists before, so I couldn't explain why it's undefined. After logging the container I saw it:
container is available, initial objects: {exampleMap: SharedMap}

The container already existed in the meeting (with the exampleMap from the minimal example I started earlier). So the live-share-turbo client in live-share-react took this existing container, but could not create it's internal TURBO_STATE_MAP object, but assumes that it's already there then breaks with the error above.

So I asked myself how this situation could be handled in Teams where maybe more then one live-share-* app is started in the same meeting. The first will win? But how should the second app handle this?

It would be nice if you could give me some guidance on this. Many thanks in advance for your support.

Many greetings
Tobias

from live-share-sdk.

nmtoblum avatar nmtoblum commented on May 30, 2024

Hello Ryan,

thank you for all the information. It all helps me a lot to understand how it works. I'm also glad to hear that (vanilla) live-share will be 1.0 soon. Then with that we can build solutions that can be used productively later on.

Thanks also for the information on how new containers are created. If a new container is created per application ID and meeting, then no problems are to be expected and the observed irregularities can only be attributed to my unsuitable development setup. Now I simply create a new meeting more often. That makes it less complicated.

Otherwise, as soon as possible, I will just work a bit more with live-share(-react) and also onboard my colleagues. I have a few ideas for apps. If I run into any problems or questions along the way, I won't hesitate to post them again. Thanks again for the super helpful support.

Many greetings
Tobias

from live-share-sdk.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.