From b1440e5a7061931b9996555c092e33ba9f282d12 Mon Sep 17 00:00:00 2001 From: Steve Malmskog <2850029+stevemns@users.noreply.github.com> Date: Thu, 26 Apr 2018 20:35:41 -0700 Subject: [PATCH 1/2] Remove redundant drop function doc section Drop function description was moved up adjacent to the other functions to provide better document flow making this section redundant, hence its removal. --- .../sphinx/source/class-scheduling.rst | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/documentation/sphinx/source/class-scheduling.rst b/documentation/sphinx/source/class-scheduling.rst index 96bae95a1c..b8b257a8e2 100644 --- a/documentation/sphinx/source/class-scheduling.rst +++ b/documentation/sphinx/source/class-scheduling.rst @@ -247,23 +247,6 @@ Idempotence Occasionally, a transaction might be retried even after it succeeds (for example, if the client loses contact with the cluster at just the wrong moment). This can cause problems if transactions are not written to be idempotent, i.e. to have the same effect if committed twice as if committed once. There are generic design patterns for :ref:`making any transaction idempotent `, but many transactions are naturally idempotent. For example, all of the transactions in this tutorial are idempotent. -Dropping with limited seats ---------------------------- - -Let's finish up the limited seats feature by modifying the drop function: - -.. code-block:: python - :emphasize-lines: 4,5 - - @fdb.transactional - def drop(tr, s, c): - rec = attends.pack((s, c)) - if not tr[rec].present(): return # not taking this class - tr[course.pack((c,))] = fdb.tuple.pack((fdb.tuple.unpack(tr[course.pack((c,))])[0] + 1,)) - del tr[rec] - -This case is easier than signup because there are no constraints we can hit. We just need to make sure the student is in the class and to "give back" one seat when the student drops. - More features?! --------------- From 6a8f1ae2c16322a87431a758641da57d4afdc6bf Mon Sep 17 00:00:00 2001 From: Steve M <2850029+stevemns@users.noreply.github.com> Date: Mon, 23 Apr 2018 08:12:57 -0700 Subject: [PATCH 2/2] Fixups for python tutorial documentation The available_classes function is using Subspace.unpack to obtain the tuple, not fdb.tuple so update the description to reflect this. The limited seat tutorial section was missing the code and text describing the update of the drop function. --- documentation/sphinx/source/class-scheduling.rst | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/documentation/sphinx/source/class-scheduling.rst b/documentation/sphinx/source/class-scheduling.rst index b8b257a8e2..732c04cfb8 100644 --- a/documentation/sphinx/source/class-scheduling.rst +++ b/documentation/sphinx/source/class-scheduling.rst @@ -170,7 +170,7 @@ Before students can do anything else, they need to be able to retrieve a list of def available_classes(tr): return [course.unpack(k)[0] for k, v in tr[course.range(())]] -In general, the :meth:`Subspace.range` method returns a Python ``slice`` representing all the key-value pairs starting with the specified tuple. In this case, we want all classes, so we call :meth:`course.range` with the empty tuple ``()``. FoundationDB's ``tr[slice]`` function returns an iterable list of key-values in the range specified by the slice. We unpack the key ``k`` and value ``v`` in a comprehension. To extract the class name itself, we unpack the key into a tuple using the :py:mod:`fdb.tuple` module and take its third part. (The first and second parts are the prefixes for the ``scheduling`` and ``course`` subspaces, respectively.) +In general, the :meth:`Subspace.range` method returns a Python ``slice`` representing all the key-value pairs starting with the specified tuple. In this case, we want all classes, so we call :meth:`course.range` with the empty tuple ``()``. FoundationDB's ``tr[slice]`` function returns an iterable list of key-values in the range specified by the slice. We unpack the key ``k`` and value ``v`` in a comprehension. To extract the class name itself, we unpack the key into a tuple using the :meth:`Subspace.unpack` method and take the first field. (The first and second parts of the tuple, the ``scheduling`` and ``course`` subspace prefixes, are removed by the ``unpack`` hence the reason we take the first field of the tuple.) Signing up for a class ---------------------- @@ -232,6 +232,19 @@ This is easy -- we simply add a condition to check that the value is non-zero. L We now have to check that we aren't already signed up, since we don't want a double sign up to decrease the number of seats twice. Then we look up how many seats are left to make sure there is a seat remaining so we don't push the counter into the negative. If there is a seat remaining, we decrement the counter. +Similarly, the ``drop`` function is modified as follows: + +.. code-block:: python + :emphasize-lines: 4,5 + + @fdb.transactional + def drop(tr, s, c): + rec = attends.pack((s, c)) + if not tr[rec].present(): return # not taking this class + tr[course.pack((c,))] = fdb.tuple.pack((fdb.tuple.unpack(tr[course.pack((c,))])[0] + 1,)) + del tr[rec] + +Once again we check to see if the student is signed up and if not, we can just return as we don't want to incorrectly increase the number of seats. We then adjust the number of seats by one by taking the current value, incrementing it by one, and then storing back. Concurrency and consistency ---------------------------