Hi guys. Where can I read about `stickyBucketAssig...
# ask-questions
m
Hi guys. Where can I read about
stickyBucketAssignmentDocs
? I'm using Nextjs and I want to enable sticky bucketing, Growthbook is inited via
initSync
on React client.. which suddenly requires that unknown field. I cannot get any useful documentation about it.
h
The SDK shouldn't be requiring
stickyBucketAssignmentDocs
on
initSync
or anywhere for that matter. Would you mind sharing where you are seeing this requirement?
m
but it does require that
image.png
h
Ah, I thought you were referring to a typescript issue. You should be able to hydrate this value via
gb.getStickyBucketAssignmentDocs()
m
em.. how?) I need to pass this in constructor and it means that
gb
does not exist at this stage
image.png
h
You should still be able to pass via
Copy code
gBook.initSync({
  payload,
  stickyBucketAssignmentDocs: gBook.getStickyBucketAssignmentDocs(),
}),
Does this work?
m
stickyBucketAssignmentDocs
must be passed in constructor and not in initSync.
1st step is to create
gb
instance with required attributes, 2d is to initialize it.
stickyBucketAssignmentDocs
is required on 1st step
h
ah apologies. I think we probably need to polish up our example repo to make this easier / clearer. I don't know the exact solution, but an idea... The SDK itself has a helper for this which is async, but doesn't necessarily need to be async. Can you use the sync version of this method to generate the docs?
Copy code
function getAllStickyBucketAssignmentDocs(
  stickyBucketService: StickyBucketService,
  attributes: Attributes,
  payload: FeatureApiResponse,
) {
  // @ts-ignore
  const ctx = { global: {} };
  const attributes = getStickyBucketAttributes(ctx, payload);
  return stickyBucketService.getAllAssignments(attributes);
}
m
example repo
I'm using Nextjs and in examples repo there is no case with sticky bucketing at all šŸ˜…
Can you use the sync version of this method to generate the docs?
let me try
h
there is a rabbit hold on imports I realize. You might need to extract a few more methods
m
The SDK itself has a helper for this
are you referring to
getStickyBucketAttributes
?
h
Apologies here, this is not a great dev experience. We'll make a note to build an easier way to handle this. But meanwhile, I think we can probably get a solution working for you. So yeah,
getStickyBucketAttributes
will need to be extracted from the SDK codebase as well.
Copy code
function getStickyBucketAttributes(
  ctx: EvalContext,
  data?: FeatureApiResponse
): Record<string, string> {
  const attributes: Record<string, string> = {};
  const stickyBucketIdentifierAttributes = deriveStickyBucketIdentifierAttributes(
    ctx,
    data
  );
  stickyBucketIdentifierAttributes.forEach((attr) => {
    const { hashValue } = getHashAttribute(ctx, attr);
    attributes[attr] = toString(hashValue);
  });
  return attributes;
}
and likely also
deriveStickyBucketIdentifierAttributes
Copy code
function deriveStickyBucketIdentifierAttributes(
  ctx: EvalContext,
  data?: FeatureApiResponse
) {
  const attributes = new Set<string>();
  const features =
    data && data.features ? data.features : ctx.global.features || {};
  const experiments =
    data && data.experiments ? data.experiments : ctx.global.experiments || [];
  Object.keys(features).forEach((id) => {
    const feature = features[id];
    if (feature.rules) {
      for (const rule of feature.rules) {
        if (rule.variations) {
          attributes.add(rule.hashAttribute || "id");
          if (rule.fallbackAttribute) {
            attributes.add(rule.fallbackAttribute);
          }
        }
      }
    }
  });
  experiments.map((experiment) => {
    attributes.add(experiment.hashAttribute || "id");
    if (experiment.fallbackAttribute) {
      attributes.add(experiment.fallbackAttribute);
    }
  });
  return Array.from(attributes);
}
it's also possible that I'm missing something obvious here
m
Do you know if it's safe to
Copy code
import { getHashAttribute } from "@growthbook/growthbook/dist/core";
import {
  EvalContext,
  FeatureApiResponse,
} from "@growthbook/growthbook/dist/types/growthbook";
?
I mean this
@growthbook/growthbook/dist/core
looks a bit risky since it reaches deep content of a package
h
in terms of stability of those methods, yes, they pretty much never change. Whether or not you can import from /dist is more about your project's config/compilation settings
m
I guess
getHashAttribute
also has to be extracted from the SDK
h
yeah
well silver lining here is we're actively looking at improving the Next 13+ dev experience this quarter, and this gives us more feedback to work with! šŸ˜…
šŸ™Œ 1
m
ok, last element of the puzzle is from where I should get "data"?
Today I tried to reverse-engeneer what has to be sent to
stickyBucketAssignmentDocs
which was not that hard because you guys provide interfaces 😊:
and I created a function
Copy code
const savedAssignments = JSON.parse(
    getCookie(
      stickyBucketService.getKey(
        "id",
        (getCookie(GB_UUID_COOKIE) || "",
      ),
    ) || "{}",
  );
that returns
so my question is - is this correct result of home-made logic?
as you can see my function has very strict assumption about attributeName and attributeValue passed to
getKey
h
Quick reply as I’m AFK. Data is just the payload
šŸ‘Œ 1
Your logic looks fine for a simple ID field. Let me know if you run into any issues
ā¤ļø 1
m
thank you for your help, Bryce.
h
no problem, hopefully things are working ok for you. we're talking internally about how to make this better going forward